pandas将类别映射到整数值

时间:2017-02-13 23:27:48

标签: python pandas

我可以将分类列转换为其分类代码,但如何获得其映射的准确图片?例如:

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'}

以上述格式获得映射的准确方法是什么?

4 个答案:

答案 0 :(得分:6)

我用:

dict([(category, code) for code, category in enumerate(df_labels.col2.cat.categories)])

# {'a': 0, 'b': 1, 'c': 2}

答案 1 :(得分:4)

如果要将每个列/数据系列从分类转换回原始,您只需要反转在数据帧的for循环中执行的操作。有两种方法可以做到:

  1. 要返回原始系列或numpy数组,请使用Series.astype(original_dtype)np.asarray(categorical)

  2. 如果您已有代码和类别,则可以使用from_codes()构造函数在正常构造函数模式下保存factorize步骤。

  3. 请参阅pandas: Categorical Data

    使用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()会删除这样的冗余-只是它的效率要比其他方法低得多。