代码之家  ›  专栏  ›  技术社区  ›  mar

如何在熊猫的一个数据帧中对两个类别进行分类

  •  2
  • mar  · 技术社区  · 8 年前

    我有一个pd,包括两个150个类别的分类列。可能是列中的值 A 列中未显示 B 。例如

    a = pd.DataFrame({'A':list('bbaba'),  'B':list('cccaa')})
    a['A'] = a['A'].astype('category')
    a['B'] = a['B'].astype('category')
    

    输出为

    Out[217]: 
       A  B
    0  b  c
    1  b  c
    2  a  c
    3  b  a
    4  a  a
    

    还有

    cat_columns = a.select_dtypes(['category']).columns
    a[cat_columns] = a[cat_columns].apply(lambda x: x.cat.codes)
    a
    

    输出为

    Out[220]: 
       A  B
    0  1  1
    1  1  1
    2  0  1
    3  1  0
    4  0  0
    

    我的问题是 A. 这个 b 被视为 1 ,但在列中 B 这个 c 被视为 1. 。然而,我想要这样的东西:

    Out[220]: 
       A  B
    0  1  2
    1  1  2
    2  0  2
    3  1  0
    4  0  0
    

    哪一个 2 被视为 c

    请注意,我有150个不同的标签。

    3 回复  |  直到 8 年前
        1
  •  4
  •   MaxU - stand with Ukraine    8 年前

    使用 pd.Categorical() 您可以指定类别列表:

    In [44]: cats = a[['A','B']].stack().sort_values().unique()
    
    In [45]: cats
    Out[45]: array(['a', 'b', 'c'], dtype=object)
    
    In [46]: a['A'] = pd.Categorical(a['A'], categories=cats)
    
    In [47]: a['B'] = pd.Categorical(a['B'], categories=cats)
    
    In [48]: a[cat_columns] = a[cat_columns].apply(lambda x: x.cat.codes)
    
    In [49]: a
    Out[49]:
       A  B
    0  1  2
    1  1  2
    2  0  2
    3  1  0
    4  0  0
    
        2
  •  1
  •   piRSquared    8 年前

    我们可以使用 pd.factorize 一下子。

    pd.DataFrame(
        pd.factorize(a.values.ravel())[0].reshape(a.shape),
        a.index, a.columns
    )
    
       A  B
    0  0  1
    1  0  1
    2  2  1
    3  0  2
    4  2  2
    

    或者,如果要按排序的类别值进行因式分解,请使用 sort=True 论点

    pd.DataFrame(
        pd.factorize(a.values.ravel(), True)[0].reshape(a.shape),
        a.index, a.columns
    )
    
       A  B
    0  1  2
    1  1  2
    2  0  2
    3  1  0
    4  0  0
    

    或等同于 np.unique

    pd.DataFrame(
        np.unique(a.values.ravel(), return_inverse=True)[1].reshape(a.shape),
        a.index, a.columns
    )
    
       A  B
    0  1  2
    1  1  2
    2  0  2
    3  1  0
    4  0  0
    
        3
  •  0
  •   jpp    8 年前

    如果你是 只有 有兴趣转换为分类码,并能够通过字典访问映射, pd.factorize 可能更方便。

    跨列获取唯一值的算法 via @AlexRiley

    a = pd.DataFrame({'A':list('bbaba'),  'B':list('cccaa')})
    
    fact = dict(zip(*pd.factorize(pd.unique(a[['A', 'B']].values.ravel('K')))[::-1]))
    
    b = a.applymap(fact.get)
    

    结果:

       A  B
    0  0  2
    1  0  2
    2  1  2
    3  0  1
    4  1  1