Python: 逆经验累积分布函数(ECDF)?

9
我们可以使用以下方法创建 ECDF:
import numpy as np
from statsmodels.distributions.empirical_distribution import ECDF
ecdf = ECDF([3, 3, 1, 4])

获取指定点处的ECDF。

ecdf(x)

但是,如果我想知道百分位数97.5%的x值怎么办?

http://www.statsmodels.org/stable/generated/statsmodels.distributions.empirical_distribution.ECDF.html?highlight=ecdf 网站来看,似乎没有实现这个功能。

有没有其他方法可以实现?或者有其他的库可以使用?


1
你可能可以使用 sc.stats.rv_discrete(values=([3, 3, 1, 4],[0.25]*4)).ppf(0.975) 来实现一些功能,但它似乎有缺陷(尝试使用 0.5 来查看我所说的)。 - Eric
使用数值求解器简单地解决方程ecdf(x)=0.975 - Stelios
3
你不能把monotone_fn_inverter应用于ECDF吗? - MB-F
1
哦,亲爱的,步进函数没有反函数,是不是?我们能不能约定将你想要的函数定义为,比如说,满足Pr{x<=p}的最小x值? - Bill Bell
@BillBell 是的,这可以是CDF的反函数定义。我可能可以自己创建它。只是想知道最佳实践是什么。 - ZK Zhao
4个回答

12

由于经验分布函数在每个数据点处只放置1 / n的质量,所以第97.5个分位数只是大于所有其他点的97.5%的数据点。要找到此值,您可以按升序对数据进行排序并找到第0.975n个最大值。

sample = [1, 5, 2, 10, -19, 4, 7, 2, 0, -1]
n = len(sample)
sort = sorted(sample)
print sort[int(n * 0.975)]

它会产生:

10

因为我们知道对于离散分布(例如经验cdf),分位数函数的定义在这里,所以我们意识到我们必须取第0.975n个(向上取整)最大值。


8

这是我的建议。在dfs只从相当大的样本中有效估计的情况下,应使用线性插值。通过在样本中出现不同的值来获取插值线段的端点。

import statsmodels.distributions.empirical_distribution as edf
from scipy.interpolate import interp1d
import numpy as np
import matplotlib.pyplot as plt

sample = [1,4,2,6,5,5,3,3,5,7]
sample_edf = edf.ECDF(sample)

slope_changes = sorted(set(sample))

sample_edf_values_at_slope_changes = [ sample_edf(item) for item in slope_changes]
inverted_edf = interp1d(sample_edf_values_at_slope_changes, slope_changes)

x = np.linspace(0.1, 1)
y = inverted_edf(x)
plt.plot(x, y, 'ro', x, y, 'b-')
plt.show()

print ('97.5 percentile:', inverted_edf(0.975))

它会生成以下输出:
97.5 percentile: 6.75

以及这张图表。 倒置的经验累积分布函数


我认为这对于使用少量点非常有帮助。但是,在我的实际情况中,我有很多点(>10000),所以这可能对我来说有点过度。 - ZK Zhao
我认为没有必要从sample中删除重复项,以便再次计算ECDF进行采样。 interp1d可以解决这个问题,特别是如果使用kind='linear'。 因此,只需执行inverted_edf = interp1d( edf.ECDF(sample)(sample), sample ) - Manuel F

6

4
在这里你必须小心,因为NumPy的percentile和quantile函数仅在x的最小值和最大值之间插值(默认为线性),所以这与经验分布函数的反函数不同。 - fccoelho

0

确实,它进行插值,但是是在您使用的x周围的两个点之间,而不是在x的最小值和最大值之间。

来自Numpy文档

可选的method参数指定了在所需的分位数位于两个索引ij = i + 1之间时使用的方法。

来自Pandas文档

插值方法:{'linear', 'lower', 'higher', 'midpoint', 'nearest'} 这个可选参数指定了在所需的分位数位于两个数据点ij之间时使用的插值方法:

        * linear: `i + (j - i) * fraction`, where `fraction` is the

在引用例如文档内容时,您应该使用>引用符号。 - undefined

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