我正在寻找一种方法来复制Stata中的encode行为,它会将分类字符串列转换为数字列。
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
有什么建议吗?
非常感谢, 罗布
答案 0 :(得分:16)
您可以使用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
如果您希望复制Stata的行为,可以向labels
添加1:
x['cat'] = labels+1
答案 1 :(得分:8)
Stata的encode
命令以字符串变量开头,并创建一个新的整数变量,其标签映射到原始字符串变量。大熊猫的直接类比现在是分类变量类型,它从0.15开始成为大熊猫的一个完整部分(在最初询问和回答此问题后发布)。
请参阅文档here。
为了演示此示例,Stata命令将类似于:
encode cat, generate(cat2)
而pandas命令是:
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
答案 2 :(得分: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,等等。)使用它不是一个好主意。