Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Python的matplotlib中绘制经验cdf?_Python_Numpy_Statistics_Matplotlib_Scipy - Fatal编程技术网

如何在Python的matplotlib中绘制经验cdf?

如何在Python的matplotlib中绘制经验cdf?,python,numpy,statistics,matplotlib,scipy,Python,Numpy,Statistics,Matplotlib,Scipy,如何在Python的matplotlib中绘制数字数组的经验CDF?我正在寻找pylab的“hist”函数的cdf模拟 我能想到的一件事是: from scipy.stats import cumfreq a = array([...]) # my array of numbers num_bins = 20 b = cumfreq(a, num_bins) plt.plot(b) 这是正确的吗?有更简单/更好的方法吗 谢谢 这看起来(几乎)正是你想要的。两件事: 首先,结果是由四个项组成的

如何在Python的matplotlib中绘制数字数组的经验CDF?我正在寻找pylab的“hist”函数的cdf模拟

我能想到的一件事是:

from scipy.stats import cumfreq
a = array([...]) # my array of numbers
num_bins =  20
b = cumfreq(a, num_bins)
plt.plot(b)
这是正确的吗?有更简单/更好的方法吗

谢谢

这看起来(几乎)正是你想要的。两件事:

首先,结果是由四个项组成的元组。第三是垃圾箱的大小。第二个是最小箱子的起点。第一个是每个箱子内部或下方的点数。(最后一个是超出限制的点数,但由于您尚未设置任何点数,因此将对所有点数进行装箱。)

第二,您需要重新缩放结果,使最终值为1,以遵循CDF的常规约定,但除此之外,它是正确的

以下是它在引擎盖下的功能:

def cumfreq(a, numbins=10, defaultreallimits=None):
    # docstring omitted
    h,l,b,e = histogram(a,numbins,defaultreallimits)
    cumhist = np.cumsum(h*1, axis=0)
    return cumhist,l,b,e
它进行组织编程,然后生成每个箱子中计数的累积和。因此,结果的第i个值是小于或等于第i个bin最大值的数组值的数量。因此,最终值只是初始数组的大小

最后,要绘制它,需要使用箱子的初始值和箱子大小来确定需要的x轴值

另一个选项是使用
numpy.histogram
,它可以进行标准化并返回bin边。您需要自己计算结果计数的累积和

a = array([...]) # your array of numbers
num_bins = 20
counts, bin_edges = numpy.histogram(a, bins=num_bins, normed=True)
cdf = numpy.cumsum(counts)
pylab.plot(bin_edges[1:], cdf)

bin_edges[1::
是每个bin的上边缘。)

您想对CDF做什么? 这是一个开始。您可以尝试几个不同的值,如下所示:

from __future__ import division
import numpy as np
from scipy.stats import cumfreq
import pylab as plt

hi = 100.
a = np.arange(hi) ** 2
for nbins in ( 2, 20, 100 ):
    cf = cumfreq(a, nbins)  # bin values, lowerlimit, binsize, extrapoints
    w = hi / nbins
    x = np.linspace( w/2, hi - w/2, nbins )  # care
    # print x, cf
    plt.plot( x, cf[0], label=str(nbins) )

plt.legend()
plt.show()
列出了存储箱数量的各种规则,例如
num_-bins~sqrt(len(a))

(小字:这里发生了两件完全不同的事情

  • 对原始数据进行装箱/组织编程
  • plot
    通过所述20个组合值插值平滑曲线
这两种方法中的任何一种都可能在“笨拙”的数据上出现偏差 或者有长尾巴,即使是一维数据——二维、三维数据变得越来越困难。
另见 和 ).

您可以使用库中的函数:

版本为0.4的scicits.statsmodels已重命名为
ECDF
现在位于
distributions
模块中(折旧时)


我对AFoglia的方法做了一个小小的补充,使CDF标准化

n_counts,bin_edges = np.histogram(myarray,bins=11,normed=True) 
cdf = np.cumsum(n_counts)  # cdf not normalized, despite above
scale = 1.0/cdf[-1]
ncdf = scale * cdf

对历史进行规范化使其整体统一,这意味着cdf不会被规范化。您必须自己缩放它。

您是否尝试过pyplot.hist的cumulative=True参数?

如果您喜欢
linspace
并且更喜欢单行程序,您可以执行以下操作:

a = array([...]) # your array of numbers
num_bins = 20
counts, bin_edges = numpy.histogram(a, bins=num_bins, normed=True)
cdf = numpy.cumsum(counts)
pylab.plot(bin_edges[1:], cdf)
plt.plot(np.sort(a), np.linspace(0, 1, len(a), endpoint=False))
考虑到我的品味,我几乎总是这样做:

# a is the data array
x = np.sort(a)
y = np.arange(len(x))/float(len(x))
plt.plot(x, y)
即使存在
>O(1e6)
数据值,这也适用于我。 如果你真的需要下样品,我会设置

x = np.sort(a)[::down_sampling_step]
Edit回复关于我为什么使用上述
endpoint=False
y
的评论/编辑。以下是一些技术细节

经验CDF通常被正式定义为

CDF(x) = "number of samples <= x"/"number of samples"
它介于这两个约定之间。实际上,它说“有一个
1/(2N)
的概率比我在样本中看到的最低值小,还有一个
1/(2N)
的概率比我到目前为止看到的最大值大

请注意,此约定的选择会与中使用的
where
参数交互,如果显示它似乎更有用 CDF作为一个piecwise常量函数。为了精确匹配上述形式定义,需要使用建议的
y=[0,1/N..,1-1/N]
约定,或
where=post
y=[1/N,2/N…1]
约定,但不是相反


然而,对于大样本和合理分布,答案主体中给出的约定很容易编写,是真实CDF的无偏估计,并且与下采样方法一起使用。

如果您想显示实际的真实ECDF(正如David B所指出的,这是一个阶跃函数,在n个数据点中的每一个都增加1/n),我的建议是编写代码为每个数据点生成两个“绘图”点:

a = array([...]) # your array of numbers
sorted=np.sort(a)
x2 = []
y2 = []
y = 0
for x in sorted: 
    x2.extend([x,x])
    y2.append(y)
    y += 1.0 / len(a)
    y2.append(y)
plt.plot(x2,y2)

通过这种方式,您将获得具有ECDF特征的n个步骤的绘图,这对于足够小的数据集来说尤其好,因为这些数据集足以让步骤可见。此外,不需要使用直方图进行任何分块(这可能会给绘制的ECDF带来偏差)

import numpy as np
from matplotlib import pyplot as plt

data = np.random.randn(11)

levels = np.linspace(0, 1, len(data) + 1)  # endpoint 1 is included by default
plt.step(sorted(list(data) + [max(data)]), levels)
手动添加了
max(data)
处的最终垂直线。否则,绘图仅在
1-1/len(data)
级别停止

或者,我们可以使用
where='post'
选项来
step()

在这种情况下,不绘制从零开始的初始垂直线。

(这是我对问题的答案的副本:)

CDF或累积分布函数图基本上是一个图形,在X轴上是排序值,在Y轴上是累积分布。因此,我将创建一个新系列,将排序值作为索引,将累积分布作为值

首先创建一个示例系列:

import pandas as pd
import numpy as np
ser = pd.Series(np.random.normal(size=100))
对序列进行排序:

ser = ser.order()
现在,在继续之前,再次追加最后一个(也是最大的)值。这一步骤非常重要,尤其是对于小样本量,以便获得无偏CDF:

ser[len(ser)] = ser.iloc[-1]
创建一个新系列,将排序值作为索引,将累积分布作为值

cum_dist = np.linspace(0.,1.,len(ser))
ser_cdf = pd.Series(cum_dist, index=ser)
最后,将函数绘制为以下步骤:

ser_cdf.plot(drawstyle='steps')

一行基于Dave的回答:

plt.plot(np.sort(arr), np.linspace(0, 1, len(arr), endpoint=False))
编辑:这也是hans_meine在评论中提出的。

这是使用bokeh

from bokeh.plotting import figure, show
from statsmodels.distributions.empirical_distribution import ECDF
ecdf = ECDF(pd_series)
p = figure(title="tests", tools="save", background_fill_color="#E8DDCB")
p.line(ecdf.x,ecdf.y)
show(p)

假设VAL保存您的值,则您可以简单地按如下方式绘制CDF:

y = numpy.arange(0, 101)
x = numpy.percentile(vals, y)
plot(x, y)
按比例
plt.plot(np.sort(arr), np.linspace(0, 1, len(arr), endpoint=False))
from bokeh.plotting import figure, show
from statsmodels.distributions.empirical_distribution import ECDF
ecdf = ECDF(pd_series)
p = figure(title="tests", tools="save", background_fill_color="#E8DDCB")
p.line(ecdf.x,ecdf.y)
show(p)
y = numpy.arange(0, 101)
x = numpy.percentile(vals, y)
plot(x, y)
import seaborn as sns
sns.kdeplot(a, cumulative=True)
def empirical_cdf(x, data):
    "evaluate ecdf of data at points x"
    return np.mean(data[None, :] <= x[:, None], axis=1)
def empirical_cdf(x, data):
    "evaluate ecdf of data at points x"
    data = np.sort(data)
    return np.searchsorted(data, x)/float(data.size)
def plot_cdf( data, xaxis = None, figsize = (20,10), line_style = 'b-',
ball_style = 'bo', xlabel = r"Random variable $X$", ylabel = "$N$-samples
empirical CDF $F_{X,N}(x)$" ):
     # Contribution of each data point to the empirical distribution
     weights = 1/data.size * np.ones_like( data )
     # CDF estimation
     cdf = np.cumsum( weights )
     # Plot central part of the CDF
     plt.figure( figsize = (20,10) )
     plt.step( np.sort( a ), cdf, line_style, where = 'post' )
     # Plot valid points at discontinuities
     plt.plot( np.sort( a ), cdf, ball_style )
     # Extract plot axis and extend outside the data range
     if not xaxis == None:
         (xmin, xmax, ymin, ymax) = plt.axis( )
         xmin = xaxis[0]
         xmax = xaxis[1]
         plt.axis( [xmin, xmax, ymin, ymax] )
     else:
         (xmin,xmax,_,_) = plt.axis()
         plt.plot( [xmin, a.min(), a.min()], np.zeros( 3 ), line_style )
     plt.plot( [a.max(), xmax], np.ones( 2 ), line_style )
     plt.xlabel( xlabel )
     plt.ylabel( ylabel )
us_census_data = pd.read_csv('acs2015_census_tract_data.csv')

population = us_census_data['TotalPop'].dropna()

## sort the unique values using pandas unique function
unique_pop = np.sort(population.unique())
cdf = np.arange(0,len(unique_pop),step=1)/(len(unique_pop)-1)

## plotting    
plt.plot(unique_pop,cdf)
plt.show()