在Python的numpy或者scipy中,有没有和R中的ecdf(x)(x)
函数等价的函数?ecdf(x)(x)
和下面这个语句基本一致吗:
import numpy as np
def ecdf(x):
# normalize X to sum to 1
x = x / np.sum(x)
return np.cumsum(x)
还是需要其他东西吗?
编辑 如何控制ecdf
使用的箱数?
在Python的numpy或者scipy中,有没有和R中的ecdf(x)(x)
函数等价的函数?ecdf(x)(x)
和下面这个语句基本一致吗:
import numpy as np
def ecdf(x):
# normalize X to sum to 1
x = x / np.sum(x)
return np.cumsum(x)
还是需要其他东西吗?
编辑 如何控制ecdf
使用的箱数?
ecdf
的OP实现有误,不应该对值进行cumsum()
操作。因此,应该使用ys = np.cumsum(1 for _ in x)/float(len(x))
或更好的ys = np.arange(1, len(x)+1)/float(len(x))
而不是ys = np.cumsum(x)/np.sum(x)
如果你可以接受额外的依赖关系,则可以选择使用statmodels
的ECDF
,否则可以提供自己的实现。请参阅以下内容:
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.distributions.empirical_distribution import ECDF
%matplotlib inline
grades = (93.5,93,60.8,94.5,82,87.5,91.5,99.5,86,93.5,92.5,78,76,69,94.5,
89.5,92.8,78,65.5,98,98.5,92.3,95.5,76,91,95,61)
def ecdf_wrong(x):
xs = np.sort(x) # need to be sorted
ys = np.cumsum(xs)/np.sum(xs) # normalize so sum == 1
return (xs,ys)
def ecdf(x):
xs = np.sort(x)
ys = np.arange(1, len(xs)+1)/float(len(xs))
return xs, ys
xs, ys = ecdf_wrong(grades)
plt.plot(xs, ys, label="wrong cumsum")
xs, ys = ecdf(grades)
plt.plot(xs, ys, label="handwritten", marker=">", markerfacecolor='none')
cdf = ECDF(grades)
plt.plot(cdf.x, cdf.y, label="statmodels", marker="<", markerfacecolor='none')
plt.legend()
plt.show()
尝试这些链接:
示例代码
import numpy as np
from statsmodels.distributions.empirical_distribution import ECDF
import matplotlib.pyplot as plt
data = np.random.normal(0,5, size=2000)
ecdf = ECDF(data)
plt.plot(ecdf.x,ecdf.y)
def ecdf(x):
x = np.sort(x)
n = len(x)
def _ecdf(v):
# side='right' because we want Pr(x <= v)
return (np.searchsorted(x, v, side='right') + 1) / n
return _ecdf
np.random.seed(42)
X = np.random.normal(size=10_000)
Fn = ecdf(X)
Fn([3, 2, 1]) - Fn([-3, -2, -1])
## array([0.9972, 0.9533, 0.682 ])
如图所示,它给出了正态分布的正确的68-95-99.7%概率。
这位作者提供了一个非常好的由用户编写的ECDF函数示例:John Stachurski的Python讲座。他的讲座系列面向计算经济学研究生;然而,对于任何学习Python中的普通科学计算的人来说,它们都是我的首选资源。
编辑:现在已经过去一年了,但我认为我仍然可以回答你问题中的“编辑”部分,以防你(或其他人)认为这仍然有用。
ECDF中没有像直方图那样的“箱子”。如果G是使用数据向量Z形成的经验分布函数,则G(x)字面上是Z <= x的发生次数除以len(Z)。这不需要“装箱”来确定。因此,在某种意义上,ECDF保留了关于数据集的所有可能信息(因为它必须保留整个数据集进行计算),而直方图实际上通过装箱失去了一些关于数据集的信息。出于这个原因,当可能时,我更喜欢使用ECDF而不是直方图。
有趣的奖励:如果您需要从非常大的流数据创建小型ECDF类似对象,您应该查看McDermott等人的这篇“数据骨架”论文。
SciPy 1.11 最终获得了一个内置的 scipy.stats.ecdf(sample)
函数。
对于给定的 sample
一维数组对象,例如列表,该函数返回一个表示该样本的估计的经验累积分布函数的对象 cdf
,以及一个表示该样本的经验生存函数的对象 sf
。
问题要求找到 R 中 ecdf(x)(x)
的等价物。假设在两种情况下,x
都表示实际样本,使用新的 SciPy 函数的等价物将是 scipy.stats.ecdf(sample).cdf.probabilities
。
假设在第一种情况下,x
只表示实际样本,而第二种情况应该是估计 cdf 的函数参数,则等价物将是 scipy.stats.ecdf(sample).cdf.eval(x)
。
data <- c(10, 20, 50, 40, 40, 30, 60, 70, 80, 90)
# Define a function to compute the ECDF
ecdf_func <- function(data) {
Length <- length(data)
sorted <- sort(data)
ecdf <- rep(0, Length)
for (i in 1:Length) {
ecdf[i] <- sum(sorted <= data[i]) / Length
}
return(ecdf)
}
ecdf <- ecdf_func(data)
print(ecdf)
输出: [1] 0.1 0.2 0.6 0.5 0.5 0.3 0.7 0.8 0.9 1.0
# With stats library
library(stats)
ecdf_fun <- ecdf(data)
ecdf_ <- ecdf_fun(data)
print(ecdf_)
输出: [1] 0.1 0.2 0.6 0.5 0.5 0.3 0.7 0.8 0.9 1.0