numpy/scipy中有类似R中ecdf(x)(x)函数的等效函数吗?

28

在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使用的箱数?


3
这个应该有帮助:https://dev59.com/LXA75IYBdhLWcg3wlqSh - agstudy
6个回答

32

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)

如果你可以接受额外的依赖关系,则可以选择使用statmodelsECDF,否则可以提供自己的实现。请参阅以下内容:

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()

ECDF comparison


22

尝试这些链接:

statsmodels.ECDF

Python中没有阶梯函数的ECDF?

示例代码

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)

6
用Scipy不行吗? - Zhubarb

7
在R中,ecdf函数返回经验累积分布函数,因此其确切等效项应该是:
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%概率


6

这位作者提供了一个非常好的由用户编写的ECDF函数示例:John Stachurski的Python讲座。他的讲座系列面向计算经济学研究生;然而,对于任何学习Python中的普通科学计算的人来说,它们都是我的首选资源。

编辑:现在已经过去一年了,但我认为我仍然可以回答你问题中的“编辑”部分,以防你(或其他人)认为这仍然有用。

ECDF中没有像直方图那样的“箱子”。如果G是使用数据向量Z形成的经验分布函数,则G(x)字面上是Z <= x的发生次数除以len(Z)。这不需要“装箱”来确定。因此,在某种意义上,ECDF保留了关于数据集的所有可能信息(因为它必须保留整个数据集进行计算),而直方图实际上通过装箱失去了一些关于数据集的信息。出于这个原因,当可能时,我更喜欢使用ECDF而不是直方图。

有趣的奖励:如果您需要从非常大的流数据创建小型ECDF类似对象,您应该查看McDermott等人的这篇“数据骨架”论文。


4
链接已经失效。作者将他的Python讲座迁移到了http://quant-econ.net/py/index.html。 - bersanri
1
新链接也是失效的。也许这是新的(希望是永久的)链接?https://python.quantecon.org/intro.html - Sterling

1

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)


1
好的,谢谢!目前我跳过了一个更实际的用法示例,因为我还没有使用足够新的SciPy版本来包含这个功能。 - undefined

0
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


我们的答案可以通过提供更多支持性信息来改进。请编辑并添加进一步的细节,例如引用或文档,以便他人可以确认您的答案是正确的。您可以在帮助中心找到有关如何编写好答案的更多信息。 - Simas Joneliunas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接