【问题标题】:Plotting a histogram in Pandas with very heavy-tailed data在 Pandas 中绘制带有非常重尾数据的直方图
【发布时间】: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 索引以表示百分比出现次数而不是绝对次数。但是,我不明白我将如何自动执行此操作。

【问题讨论】:

    标签: python matplotlib pandas histogram ipython-notebook


    【解决方案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
    

    然后你可以用你喜欢的任何方式进行绘图。

    【讨论】:

      猜你喜欢
      • 2021-09-29
      • 2021-07-28
      • 2013-11-04
      • 1970-01-01
      • 1970-01-01
      • 2015-01-07
      • 1970-01-01
      • 2011-04-21
      • 1970-01-01
      相关资源
      最近更新 更多