分组后对Pandas分类标签进行排序
我正在使用 pd.cut
来把一个数据集分成不同的部分,一切都很顺利。不过,我有个问题,关于 Categorical
这种对象类型,它是 pd.cut
返回的数据类型。文档上说 Categorical
对象就像是一个字符串数组,所以我看到分组时标签是按字母顺序排列的也不奇怪。
比如,下面这段代码:
df = pd.DataFrame({'value': np.random.randint(0, 10000, 100)})
labels = []
for i in range(0, 10000, 500):
labels.append("{0} - {1}".format(i, i + 499))
df.sort(columns=['value'], inplace=True, ascending=True)
df['value_group'] = pd.cut(df.value, range(0, 10500, 500), right=False, labels=labels)
df.groupby(['value_group'])['value_group'].count().plot(kind='bar')
生成了下面这个图表:
(注意中间的 500-599)
在分组之前,结构是我预期的顺序:
In [94]: df['value_group']
Out [94]:
59 0 - 499
58 0 - 499
0 500 - 999
94 500 - 999
76 500 - 999
95 1000 - 1499
17 1000 - 1499
48 1000 - 1499
我尝试了很长时间,唯一能避免这个问题的方法就是在标签前加一个字母,比如 ['A) 0 - 499', 'B) 500-999', ... ]
,这让我觉得很别扭。我还考虑过提供一个自定义的分组实现,但似乎不太可能(或者说也不是正确的做法)。我到底漏掉了什么呢?
3 个回答
1
如果你能看到这个答案的最后部分,只需要加上 sorted=False
这个参数,就可以保持原来的排序顺序了:
df.groupby(['value_group'], sorted=False)['value_group'].count().plot(kind='bar')
2
你可以对你的数据进行自定义排序。假设:
group = df.groupby(['value_group'])['value_group'].count()
sortd= group.reindex_axis(sorted(group.index, key=lambda x: int(x.split("-")[0])))
然后如果你把排序后的数据画出来,就能正常显示了。
2
我也遇到过这个问题。可能最好的解决办法是增强对分类对象的原生支持,但在此之前,我通常通过最后一次排序来解决这个问题:
In [104]: z = df.groupby('value_group').size()
In [105]: z[sorted(z.index, key=lambda x: float(x.split()[0]))]
Out[105]:
0 - 499 5
500 - 999 6
1000 - 1499 4
1500 - 1999 6
2000 - 2499 4
2500 - 2999 6
3000 - 3499 3
3500 - 3999 3
4000 - 4499 2
4500 - 4999 6
5000 - 5499 6
5500 - 5999 5
6000 - 6499 6
6500 - 6999 2
7000 - 7499 9
7500 - 7999 3
8000 - 8499 7
8500 - 8999 6
9000 - 9499 5
9500 - 9999 6
dtype: int64
In [106]: z[sorted(z.index, key=lambda x: float(x.split()[0]))].plot(kind='bar')
Out[106]: <matplotlib.axes.AxesSubplot at 0xbe87d30>