在 Pandas 中绘制带有非常重尾数据的直方图
Posted
技术标签:
【中文标题】在 Pandas 中绘制带有非常重尾数据的直方图【英文标题】:Plotting a histogram in Pandas with very heavy-tailed data 【发布时间】:2014-10-08 19:09:43 【问题描述】:我经常处理具有非常“长尾”的数据。我想绘制直方图来总结分布,但是当我尝试使用 pandas 时,我最终会得到一个条形图,其中有一个巨大的可见条,而其他所有内容都是不可见的。
这是我正在使用的系列的一个示例。因为它很长,所以我使用了 value_counts(),所以它适合这个页面。
In [10]: data.value_counts.sort_index()
Out[10]:
0 8012
25 3710
100 10794
200 11718
300 2489
500 7631
600 34
700 115
1000 3099
1200 1766
1600 63
2000 1538
2200 41
2500 208
2700 2138
5000 515
5500 201
8800 10
10000 10
10900 465
13000 9
16200 74
20000 518
21500 65
27000 64
53000 82
56000 1
106000 35
530000 3
我猜测答案涉及以某种方式将不太常见的结果分成更大的组(53000、56000、106000 和 53000 到一组 >50000 等),并且还更改 y 索引以表示百分比出现次数而不是绝对次数。但是,我不明白我将如何自动执行此操作。
【问题讨论】:
【参考方案1】:import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
mydict = 0: 8012,25: 3710,100: 10794,200: 11718,300: 2489,500: 7631,600: 34,700: 115,1000: 3099,1200: 1766,1600: 63,2000: 1538,2200: 41,2500: 208,2700: 2138,5000: 515,5500: 201,8800: 10,10000: 10,10900: 465,13000: 9,16200: 74,20000: 518,21500: 65,27000: 64,53000: 82,56000: 1,106000: 35,530000: 3
mylist = []
for key in mydict:
for e in range(mydict[key]):
mylist.insert(0,key)
df = pd.DataFrame(mylist,columns=['value'])
df2 = df[df.value <= 5000]
绘制为条形:
fig = df.value.value_counts().sort_index().plot(kind="bar")
plt.savefig("figure.png")
作为直方图(限制为 5000 及以下的值 > 97% 的数据): 我喜欢使用 linspace 来控制存储桶。
df2 = df[df.value <= 5000]
df2.hist(bins=np.linspace(0,5000,101))
plt.savefig('hist1')
编辑:将 np.linspace(0,5000,100)
更改为 np.linspace(0,5000,101)
并更新直方图。
【讨论】:
我不完全确定我是如何偶然发现只是在 value_counts() 上尝试了一个普通的条形图。我想我会把这个归档在“试图超越自己”下。谢谢。【参考方案2】:使用 cumsum() 方法是过滤尾部的一种有点自动化的方法。 这样您就可以通过编程方式找到仅出现少量观察的索引:
from io import StringIO
import pandas as pd
data=("""0 8012
25 3710
100 10794
200 11718
300 2489
500 7631
600 34
700 115
1000 3099
1200 1766
1600 63
2000 1538
2200 41
2500 208
2700 2138
5000 515
5500 201
8800 10
10000 10
10900 465
13000 9
16200 74
20000 518
21500 65
27000 64
53000 82
56000 1
106000 35
530000 3
""")
d=StringIO(data)
df = pd.read_csv(d,sep='\s+',names=['value','count'],index_col='value')
total=df['count'].sum()
df2 = df[ df['count'].cumsum()/total < 0.98 ]
print(df2)
这会留下 89% 的值并丢弃其余的值。
输出是:
count
value
0 8012
25 3710
100 10794
200 11718
300 2489
500 7631
600 34
700 115
1000 3099
1200 1766
1600 63
2000 1538
2200 41
2500 208
2700 2138
5000 515
5500 201
8800 10
10000 10
然后你可以用你喜欢的任何方式进行绘图。
【讨论】:
以上是关于在 Pandas 中绘制带有非常重尾数据的直方图的主要内容,如果未能解决你的问题,请参考以下文章
想要将 Pandas 数据框绘制为具有 log10 比例 x 轴的多个直方图