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

Python 如何在Pandas中的一个数据帧中对两个类别进行分类,python,pandas,indexing,categories,Python,Pandas,Indexing,Categories,我有一个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 Out[220]:

我有一个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
Out[220]: 
   A  B
0  1  1
1  1  1
2  0  1
3  1  0
4  0  0
而且

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

Out[217]: 
   A  B
0  b  c
1  b  c
2  a  c
3  b  a
4  a  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个不同的标签

使用可以指定类别列表:

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
如果您只对转换为分类代码感兴趣,并且能够通过字典访问映射,可能会更方便

跨列获取唯一值的算法

结果:

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

我们可以同时使用
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