pandas эквивалент кодирования Stata
Я ищу способ воспроизвести кодирование поведение в Stata, которое преобразует столбец категориальной строки в столбец чисел.
x = pd.DataFrame({'cat':['A','A','B'], 'val':[10,20,30]})
x = x.set_index('cat')
что приводит к:
val
cat
A 10
A 20
B 30
Я хотел бы преобразовать столбец cat из строк в целые числа, сопоставляя каждую уникальную строку с (произвольным) целым числом 1-к-1. В результате:
val
cat
1 10
1 20
2 30
или, так же хорошо:
cat val
0 1 10
1 1 20
2 2 30
какие предложения?
большое спасибо, как всегда, Роб!--7-->
3 ответов
стата по encode
команда начинается со строковой переменной и создает новую целочисленную переменную с метками, сопоставленными с исходной строковой переменной. Прямым аналогом этого в панд теперь будет категориальный переменный тип, который стал полноценной частью панд, начиная с 0.15 (который был выпущен после того, как этот вопрос был первоначально задан и ответил).
документации здесь.
чтобы продемонстрировать для этого примера, команда Stata было бы что-то вроде:
encode cat, generate(cat2)
тогда как команда панд будет:
x['cat2'] = x['cat'].astype('category')
cat val cat2
0 A 10 A
1 A 20 A
2 B 30 B
так же, как Stata делает с encode
, данные хранятся в виде целых чисел, но отображаются в виде строк в выходных данных по умолчанию.
вы можете проверить это, используя категориальный метод доступа cat
чтобы увидеть базовое целое число. (И по этой причине вы, вероятно, не хотите использовать " cat " в качестве имени столбца.)
x['cat2'].cat.codes
0 0
1 0
2 1
вы могли бы использовать pd.factorize
:
import pandas as pd
x = pd.DataFrame({'cat':('A','A','B'), 'val':(10,20,30)})
labels, levels = pd.factorize(x['cat'])
x['cat'] = labels
x = x.set_index('cat')
print(x)
доходность
val
cat
0 10
0 20
1 30
вы можете добавить 1 к labels
если вы хотите воспроизвести поведение Stata:
x['cat'] = labels+1
предполагая, что у вас есть фиксированный набор одиночных заглавных английских букв в качестве категориальной переменной, вы также можете сделать это:
x['cat'] = x.cat.map(lambda x: ord(x) - 64)
Я считаю, что это немного взломать. Но опять же, в Python лучше всего было бы определить отображение из символов в целые числа, которые вы, например,
my_map = {"A":1, ...}
# e.g.: {x:ord(x)-64 for x in string.ascii_uppercase}
# if that's the convention you happen to desire.
а потом сделай
x['cat'] = x.cat.map(lambda x: my_map[x])
или что-то подобное.
Это превосходит опору на соглашения встроенного функции для вашего целочисленного отображения по многим причинам и (IMO) это такие вещи, которые "чувствуют себя" неприятными преобразованиями программисту-аналитику, но на самом деле представляют собой важные метаданные о программном обеспечении, которое вы пишете, которые раскрывают реальную слабость глобальных функций удобства на языках более высокого уровня, таких как MATLAB, STATA и т. д. Даже если есть встроенная функция, которая случайно присоединяется к конкретному соглашению, которое вы хотите использовать (произвольное соглашение, которое " A" сопоставляется с 1, "B" сопоставляется с 2 и т. д.) это не делает его хорошей идеей, чтобы использовать его.