如何使用NumPy获得累积分布函数?

oma*_*mar 28 python numpy histogram

我想用NumPy创建一个CDF,我的代码是下一个:

histo = np.zeros(4096, dtype = np.int32)
for x in range(0, width):
   for y in range(0, height):
      histo[data[x][y]] += 1
      q = 0 
   cdf = list()
   for i in histo:
      q = q + i
      cdf.append(q)
Run Code Online (Sandbox Code Playgroud)

我正在走数组,但需要很长时间才能执行程序.有这个功能的内置功能,不是吗?

Dan*_*Dan 78

使用直方图是一种解决方案,但它涉及对数据进行分级.这对于绘制经验数据的CDF不是必需的.让我们F(x)计算有多少条目小于x它然后它上升一,正好在我们看到测量的位置.因此,如果我们对样本进行排序,那么在每个点我们将计数增加1(或者将分数增加1/N)并且将一个相对于另一个绘制,我们将看到"精确的"(即未分箱的)经验CDF.

以下代码示例演示了该方法

import numpy as np
import matplotlib.pyplot as plt

N = 100
Z = np.random.normal(size = N)
# method 1
H,X1 = np.histogram( Z, bins = 10, normed = True )
dx = X1[1] - X1[0]
F1 = np.cumsum(H)*dx
#method 2
X2 = np.sort(Z)
F2 = np.array(range(N))/float(N)

plt.plot(X1[1:], F1)
plt.plot(X2, F2)
plt.show()
Run Code Online (Sandbox Code Playgroud)

它输出以下内容

在此输入图像描述


use*_*424 17

我不确定你的代码在做什么,但如果你有hist和你bin_edges返回的数组numpy.histogram可以numpy.cumsum用来生成直方图内容的累积和.

>>> import numpy as np
>>> hist, bin_edges = np.histogram(np.random.randint(0,10,100), normed=True)
>>> bin_edges
array([ 0. ,  0.9,  1.8,  2.7,  3.6,  4.5,  5.4,  6.3,  7.2,  8.1,  9. ])
>>> hist
array([ 0.14444444,  0.11111111,  0.11111111,  0.1       ,  0.1       ,
        0.14444444,  0.14444444,  0.08888889,  0.03333333,  0.13333333])
>>> np.cumsum(hist)
array([ 0.14444444,  0.25555556,  0.36666667,  0.46666667,  0.56666667,
        0.71111111,  0.85555556,  0.94444444,  0.97777778,  1.11111111])
Run Code Online (Sandbox Code Playgroud)

  • 然而,这引入了对于累积分布不必要的分箱步骤. (12认同)
  • “由于混淆/错误行为,Numpy 1.6 中不推荐使用这个关键字 `normed`。它将在 Numpy 2.0 中删除。“如果 bin 不在 `[0,1]` 中,则代码中存在错误。添加 x=np.cumsum(hist); x=(x - x.min()) / x.ptp() (3认同)

off*_*tus 5

更新 numpy 版本 1.9.0。user545424 的答案在 1.9.0 中不起作用。这有效:

>>> import numpy as np
>>> arr = np.random.randint(0,10,100)
>>> hist, bin_edges = np.histogram(arr, density=True)
>>> hist = array([ 0.16666667,  0.15555556,  0.15555556,  0.05555556,  0.08888889,
    0.08888889,  0.07777778,  0.04444444,  0.18888889,  0.08888889])
>>> hist
array([ 0.1       ,  0.11111111,  0.11111111,  0.08888889,  0.08888889,
    0.15555556,  0.11111111,  0.13333333,  0.1       ,  0.11111111])
>>> bin_edges
array([ 0. ,  0.9,  1.8,  2.7,  3.6,  4.5,  5.4,  6.3,  7.2,  8.1,  9. ])
>>> np.diff(bin_edges)
array([ 0.9,  0.9,  0.9,  0.9,  0.9,  0.9,  0.9,  0.9,  0.9,  0.9])
>>> np.diff(bin_edges)*hist
array([ 0.09,  0.1 ,  0.1 ,  0.08,  0.08,  0.14,  0.1 ,  0.12,  0.09,  0.1 ])
>>> cdf = np.cumsum(hist*np.diff(bin_edges))
>>> cdf
array([ 0.15,  0.29,  0.43,  0.48,  0.56,  0.64,  0.71,  0.75,  0.92,  1.  ])
>>>
Run Code Online (Sandbox Code Playgroud)

  • user12287,我觉得编辑别人的答案很奇怪。此外,不同版本的答案也不同。 (2认同)

小智 5

补充丹的解决方案。如果您的样本中有几个相同的值,您可以使用 numpy.unique :

Z = np.array([1,1,1,2,2,4,5,6,6,6,7,8,8])
X, F = np.unique(Z, return_index=True)
F=F/X.size

plt.plot(X, F)
Run Code Online (Sandbox Code Playgroud)