如何在 Pandas 中对一个数据框中的两个类别进行分类
How to categorize two categories in one dataframe in Pandas
我有一个 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 个不同的标签。
使用 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
如果您只对转换为分类代码并能够通过字典访问映射感兴趣,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
我们可以一次性使用 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
我有一个 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 个不同的标签。
使用 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
如果您只对转换为分类代码并能够通过字典访问映射感兴趣,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
我们可以一次性使用 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