我使用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
我已经玩了一段时间了,我能够避免这种情况的唯一方法就是在标签前加上一个前导alpha字符,例如['A) 0 - 499', 'B) 500-999', ... ]
让我感到畏缩。我研究的其他事情是提供一个自定义的groupby实现,这似乎不可能(或者也是正确的)。我错过了什么?
答案 0 :(得分:2)
您可以对数据进行自定义排序。 让我们说:
group = df.groupby(['value_group'])['value_group'].count()
sortd= group.reindex_axis(sorted(group.index, key=lambda x: int(x.split("-")[0])))
然后,如果你绘制排序系列,它的工作原理。
答案 1 :(得分: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>
答案 2 :(得分:1)
对于真正了解这部分答案的人,只需添加sorted=False
参数即可保留原始排序:
df.groupby(['value_group'], sorted=False)['value_group'].count().plot(kind='bar')