我可以将分类列转换为其分类代码,但如何获得其映射的准确图片?例如:
df_labels = pd.DataFrame({'col1':[1,2,3,4,5], 'col2':list('abcab')})
df_labels['col2'] = df_labels['col2'].astype('category')
df_labels看起来像这样:
col1 col2
0 1 a
1 2 b
2 3 c
3 4 a
4 5 b
如何准确地将猫代码映射到猫类? 下面的stackoverflow响应表示枚举类别。但是,我不确定枚举是否是cat.codes生成整数值的方式。有更准确的方法吗?
Get mapping of categorical variables in pandas
>>> dict( enumerate(df.five.cat.categories) )
{0: 'bad', 1: 'good'}
以上述格式获得映射的准确方法是什么?
答案 0 :(得分:6)
我用:
dict([(category, code) for code, category in enumerate(df_labels.col2.cat.categories)])
# {'a': 0, 'b': 1, 'c': 2}
答案 1 :(得分:4)
如果要将每个列/数据系列从分类转换回原始,您只需要反转在数据帧的for
循环中执行的操作。有两种方法可以做到:
要返回原始系列或numpy数组,请使用Series.astype(original_dtype)
或np.asarray(categorical)
。
如果您已有代码和类别,则可以使用from_codes()
构造函数在正常构造函数模式下保存factorize步骤。
使用from_codes
与official documentation一样,它从代码和类别数组中生成一个分类类型。
splitter = np.random.choice([0,1], 5, p=[0.5,0.5])
s = pd.Series(pd.Categorical.from_codes(splitter, categories=["train", "test"]))
print splitter
print s
给出
[0 1 1 0 0]
0 train
1 test
2 test
3 train
4 train
dtype: category
Categories (2, object): [train, test]
代码
# after your previous conversion
print df['col2']
# apply from_codes, the 2nd argument is the categories from mapping dict
s = pd.Series(pd.Categorical.from_codes(df['col2'], list('abcde')))
print s
给出
0 0
1 1
2 2
3 0
4 1
Name: col2, dtype: int8
0 a
1 b
2 c
3 a
4 b
dtype: category
Categories (5, object): [a, b, c, d, e]
答案 2 :(得分:2)
已修改的答案(已移除cat.categories
并已将list
更改为dict
):
>>> dict(zip(df_labels.col2.cat.codes, df_labels.col2))
{0: 'a', 1: 'b', 2: 'c'}
一些评论所指的原始答案:
>>> list(zip(df_labels.col2.cat.codes, df_labels.col2.cat.categories))
[(0, 'a'), (1, 'b'), (2, 'c')]
正如评论所述,原始答案适用于此示例,因为前三个值恰好是[a,b,c]
,但如果它们是[c,b,a]
或[b,c,a]
则会失败。
答案 3 :(得分:2)
OP要求相对于链接问题的答案“准确”的东西:
dict(enumerate(df_labels.col2.cat.categories))
# {0: 'a', 1: 'b', 2: 'c'}
我认为以上答案确实是正确的(完整披露:这是我在捍卫的另一个问题中的答案)。还要注意,它与@pomber的答案大致等效,除了键和值的顺序相反。 (由于键和值都是唯一的,因此排序在某种意义上是无关紧要的,因此很容易反转)。
但是,以下方法可以说更安全,或者至少对其工作方式更加透明:
dict(zip(df_labels.col2.cat.codes, df_labels.col2))
# {0: 'a', 1: 'b', 2: 'c'}
这在本质上类似于@boud的答案,但是通过将df_labels.col2.cat.codes
替换为df_labels.col2
来纠正错误。还将list()
替换为dict()
,这似乎更适合映射,并自动删除重复项。
请注意,zip()
的两个参数的长度均为len(df)
,而df_labels.col2.cat.codes
的长度是唯一值的计数,通常比len(df)
短。
还要注意,此方法效率很低,因为它两次将0
映射到'a'
,并且对于'b'
也是如此。在大型数据帧中,速度差异可能很大。但这不会引起任何错误,因为dict()
会删除这样的冗余-只是它的效率要比其他方法低得多。