代码之家  ›  专栏  ›  技术社区  ›  Joël

无法在Matplotlib直方图上获取y轴以显示概率

  •  4
  • Joël  · 技术社区  · 8 年前

    我有如下数据(pd系列)(每日股票收益,n=555):

    S = perf_manual.returns
    S = S[~((S-S.mean()).abs()>3*S.std())]
    
    2014-03-31 20:00:00    0.000000
    2014-04-01 20:00:00    0.000000
    2014-04-03 20:00:00   -0.001950
    2014-04-04 20:00:00   -0.000538
    2014-04-07 20:00:00    0.000764
    2014-04-08 20:00:00    0.000803
    2014-04-09 20:00:00    0.001961
    2014-04-10 20:00:00    0.040530
    2014-04-11 20:00:00   -0.032319
    2014-04-14 20:00:00   -0.008512
    2014-04-15 20:00:00   -0.034109
    ...
    

    我想由此生成一个概率分布图。使用:

    print stats.normaltest(S)
    
    n, bins, patches = plt.hist(S, 100, normed=1, facecolor='blue', alpha=0.75)
    print np.sum(n * np.diff(bins))
    
    (mu, sigma) = stats.norm.fit(S)
    print mu, sigma
    y = mlab.normpdf(bins, mu, sigma)
    plt.grid(True)
    l = plt.plot(bins, y, 'r', linewidth=2)
    
    plt.xlim(-0.05,0.05)
    plt.show()
    

    我得到了以下信息:

    NormaltestResult(statistic=66.587382579416982, pvalue=3.473230376732532e-15)
    1.0
    0.000495624926242 0.0118790391467
    

    graph

    我试过很多StackOverflow答案,但都搞不懂。

    2 回复  |  直到 8 年前
        1
  •  10
  •   jotasi    8 年前

    (据我所知)没有简单的方法可以用 plt.hist 。但您可以使用 np.histogram 然后以任何方式规范化数据。如果我没弄错的话,你希望数据显示在给定箱子中找到一个点的概率,而不是概率分布。这意味着您必须缩放数据,使所有存储箱的总和为1 bin_probability = n/float(n.sum()) .

    然后,您将不再具有适当规范化的概率分布函数(pdf),这意味着区间上的积分将不是概率!这就是为什么你必须重新销售你的 mlab.normpdf

    因此,您最终得到的代码大致如下:

    import numpy as np
    import scipy.stats as stats
    import matplotlib.pyplot as plt
    import matplotlib.mlab as mlab
    
    # Produce test data
    S = np.random.normal(0, 0.01, size=1000)
    
    # Histogram:
    # Bin it
    n, bin_edges = np.histogram(S, 100)
    # Normalize it, so that every bins value gives the probability of that bin
    bin_probability = n/float(n.sum())
    # Get the mid points of every bin
    bin_middles = (bin_edges[1:]+bin_edges[:-1])/2.
    # Compute the bin-width
    bin_width = bin_edges[1]-bin_edges[0]
    # Plot the histogram as a bar plot
    plt.bar(bin_middles, bin_probability, width=bin_width)
    
    # Fit to normal distribution
    (mu, sigma) = stats.norm.fit(S)
    # The pdf should not normed anymore but scaled the same way as the data
    y = mlab.normpdf(bin_middles, mu, sigma)*bin_width
    l = plt.plot(bin_middles, y, 'r', linewidth=2)
    
    plt.grid(True)
    plt.xlim(-0.05,0.05)
    plt.show()
    

    结果将是:

    enter image description here

        2
  •  6
  •   Gabriel    6 年前

    当然,jotasi的答案是有效的,但我想添加一个非常简单的技巧,通过直接调用 hist .

    诀窍是使用 weights 参数默认情况下,您传递的每个数据点的权重为1。每个箱子的高度就是落入该箱子的数据点的重量之和。相反,如果我们有 n 点,我们可以简单地将每个点的权重设为 1 / n 然后,落在某个桶中的点的权重之和也是给定点位于该桶中的概率。

    在您的情况下,只需将绘图线更改为:

    n, bins, patches = plt.hist(S, weights=np.ones_like(S) / len(S),
                                facecolor='blue', alpha=0.75)