Python 相当于Stata和x27的熊猫;s编码
我正在寻找一种方法来复制Stata中的行为,它将把一个分类字符串列转换成一个数字列Python 相当于Stata和x27的熊猫;s编码,python,pandas,stata,Python,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
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
有什么建议吗
非常感谢,一如既往,
Rob您可以使用
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的行为,您可以在标签中添加1:
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,等等)使用它不是一个好主意。Stata的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对编码所做的那样,数据存储为整数,但在默认输出中显示为字符串
您可以通过使用分类访问器cat
查看基础整数来验证这一点。(因此,您可能不想使用“cat”作为列名。)
获取[0,0,1]的另一种方法是查看pd.category(seq).labels
。谢谢,@DSM。看着,我看到了Categorical
调用factorize
。谢谢@unutbu。仅供参考:这是一种制作精美分类散点图的绝妙方法,使用文本列作为分类。@unutbu这应该放在文档中,你能为附近的某个地方做公关吗:使用主回购;当0.13发布时,稳定的文档将被更新。可能是:数据帧([(i[1],i[0]),用于枚举中的i(set(x.index))]),然后合并?重要细节:这不是Stata的编码所做的。它产生一对一的映射。@NickCox我不明白这怎么不是一对一的映射。'A'
的每个实例变为1
,'B'
的每个实例变为2
等等。这不是我在您的示例中看到的。我看到A,A,B映射到10,20,30。为什么第一个A得10分,第二个得20分?如果那是你想要的,我不明白,但这取决于你;我的观点仍然是,它不是encode
在Stata中所做的。@NickCox获取映射的是cat
列,而不是val
列。val
列保持不变,与示例无关。重要的是,根据我的例子,cat
从['A','A','B']
到[1,1,2]
。我在MATLAB上给有经验的用户留下了评论。关于Stata的encode
命令的评论令人费解。它默认将不同的字符串值按字母顺序映射到整数1以上,因此“A”、“B”、“C”将映射到1、2、3。但该默认值可以通过某些指定的字符串到整数转换方案来覆盖。如果你不想要,就不要使用它;在MATLAB中,没有明显的语言设计或哲学问题。int64('A')==65
int('A')
在Python中引发一个ValueError
,这在IMHO中更有意义。当然,如果你只使用MATLAB编写代码,而不与外界交流,那么这是一个没有实际意义的问题。@Nick Cox:这完全是一个设计哲学的问题。我有8年以上的MATLAB经验,4年Python经验,2年STATA经验。STATA会有这样一个内置函数,这并不困扰我,这很好。但当有人使用该函数创建分类变量(例如,回归中的伪变量)时,我确实感到很烦恼。这意味着需要一些元数据(编码),这些元数据不应该与第三方的东西耦合,本着@Phillip Cloud的精神,我想这是一个品味的问题,人们是否期望int
以这种方式行事。因为Python中的int(x)
只是x的语法糖分。我不希望单个长度str
变量与多字符str
变量具有不同的\uuuuu int\uuuu
,这为想要像ord
这样的函数提供了区别,但这只是我的观点,您对Stata的经验并不能扩展到能够正确拼写其名称,或者知道Stata命令和Stata函数之间的区别。如果经验的长度是一个论点,那么感受一下我在斯塔塔工作22年的重量吧。更严重的是,更重要的是,你关于<代码>编码< /代码>的评论仍然令人费解,因为你已经改变了你的论点(实际上是一种断言),认为如果你用怀疑的方式来使用语言特征,那就被起诉了。这更多地反映了你的个人品味
x['cat2'].cat.codes
0 0
1 0
2 1