Python 相当于Stata和x27的熊猫;s编码

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

我正在寻找一种方法来复制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
有什么建议吗

非常感谢,一如既往,
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