如何在具有大量不同计数的pandas中绘制value_counts,而不是均匀分布

时间:2016-06-02 17:38:46

标签: python pandas plot

假设我有以下数据:

s2 = pd.Series([1,2,3,4,5,2,3,333,2,123,434,1,2,3,1,11,11,432,3,2,4,3,3,3,54,34,24,2,223,2535334,3,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30000, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2])
s2.value_counts(normalize=True).plot()

我想在图中显示的是,有一些数字构成了大多数情况。问题是这将在图的最左侧看到然后会有一条直线对于所有其他类别。 在实际数据中,x轴将分类为大约18000个类别,4%的计数将大约为10000个,然后其余的将下降并且大约为50个。

我想向#34;普通"的观众展示这个。商界人士如此难以理解难以阅读的解决方案。

更新:请参阅@unutbu answere 尝试使用元组时,更新了代码,并在qcut时收到错误。

TypeError: unsupported operand type(s) for -: 'tuple' and 'tuple'

df = pd.DataFrame({'s1':[1,0,1,0], 's2':[1,0,1,1], 's3':[1,0,1,1], 's4':[0,0,0,1]})
perms = df.apply(tuple, axis=1)
prob = perms.value_counts(normalize=True).reset_index(drop='True')
category_classes = pd.qcut(prob, q=[0, .25, 0.95, 1.], 
                 labels=['bottom 25%', 'mid 70%', 'top 5%'])
prob_groups = prob.groupby(category_classes).sum()
prob_groups.plot(kind='bar')
plt.xticks(rotation=0)
plt.show()

2 个答案:

答案 0 :(得分:16)

您可以将规范化的值计数保持在某个threshold之上。然后将threshold下面的值加在一起,并将它们聚集在一个类别中,可以称之为"其他"。

通过选择threshold足够高,您将能够显示总体概率分布的最重要贡献者,同时仍然在标记为&#34;其他&#34;:<的栏中显示尾部的大小。 / p>

import matplotlib.pyplot as plt
import pandas as pd
s2 = pd.Series([1,2,3,4,5,2,3,333,2,123,434,1,2,3,1,11,11,432,3,2,4,3,3,3,54,34,24,2,223,2535334,3,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30000, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2])
prob = s2.value_counts(normalize=True)
threshold = 0.02
mask = prob > threshold
tail_prob = prob.loc[~mask].sum()
prob = prob.loc[mask]
prob['other'] = tail_prob
prob.plot(kind='bar')
plt.xticks(rotation=25)
plt.show()

enter image description here

您可以合理地在a上显示的类别标签数量有限制 条状图。对于正常大小的图表来说,3000太多了。而且,它是 期望观众收集任何意义可能是不合理的 阅读3000个标签。

图表应该总结数据。主要观点似乎是4%或5%的类别占绝大多数案例。因此,为了推动这一点,也许可以使用pd.qcut将案例分类为简单类别,例如bottom 25%mid 70%top 5%

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

N = 18000
categories = np.arange(N)
np.random.shuffle(categories)
M = int(N*0.04)
prob = pd.Series(np.concatenate([np.random.randint(9000, 11000, size=M),
                      np.random.randint(0, 100, size=N-M), ]), index=categories)
prob /= prob.sum()
category_classes = pd.qcut(prob, q=[0, .25, 0.95, 1.], 
                 labels=['bottom 25%', 'mid 70%', 'top 5%'])
prob_groups = prob.groupby(category_classes).sum()
prob_groups.plot(kind='bar')
plt.xticks(rotation=0)
plt.show()

enter image description here

答案 1 :(得分:0)

只记录轴(我没有熊猫,但它应该相似):

$scope.profilePic