使用Pandas滚动窗口计算分位数为何与单独计算结果不一致?
为什么Pandas滚动窗口分位数与单独计算的分位数结果不一致?
这个问题的核心原因是:Pandas的rolling.quantile()和常规的DataFrame.quantile()默认采用了不同的分位数计算(插值)方法,导致相同数据的分位数结果出现差异。
具体分析你的案例
先看你的数据:第一个滚动窗口是[1,2,3],我们分别拆解两种计算方式的逻辑:
1. 单独计算df.iloc[0:3].quantile(0.75)
在现代Pandas(1.0+)中,quantile()默认使用method='linear'插值方法,计算逻辑是:
- 对窗口内数据排序:
[1,2,3] - 计算分位数位置:
(n-1)*q = (3-1)*0.75 = 1.5(n是样本数量,q是分位数) - 因为位置是小数,采用线性插值:取排序后第1位(2)和第2位(3)的中间值,即
2 + 0.5*(3-2) = 2.5,这和你得到的结果完全一致。
2. 滚动窗口计算df.rolling(3).quantile(0.75)
从你给出的结果(第一个有效窗口返回2.0)来看,你的Pandas版本大概率是1.0之前的旧版本,或者你显式指定了interpolation='lower'参数。
在旧版本Pandas中,rolling.quantile()默认使用interpolation='lower',它的逻辑是:
- 对窗口内数据排序:
[1,2,3] - 找到最小的数值,使得该数值大于等于分位数对应的理论位置的结果。对于q=0.75,理论位置是1.5,
lower插值会直接取排序后索引为1的元素(即2),不进行插值计算,所以结果是2.0。
如何让两者结果一致?
要让滚动窗口分位数和单独计算的结果匹配,只需要统一两者的插值方法:
方法1:给rolling.quantile()指定interpolation='linear'
df.rolling(window=3, center=False).quantile(0.75, interpolation='linear')
这样计算第一个窗口时就会得到2.5,和单独计算的结果完全对齐。
方法2:给单独计算的quantile()指定interpolation='lower'
df.iloc[0:3].quantile(0.75, interpolation='lower')
此时结果会是2.0,和你原来的滚动窗口结果一致。
补充说明
在Pandas 1.0及之后的版本中,rolling.quantile()的默认interpolation参数已经改为'linear',和quantile()的默认行为对齐,所以新版本中不会出现这个差异。如果你还在使用旧版本,建议考虑升级Pandas来避免这类行为不一致的问题。
内容的提问来源于stack exchange,提问作者gabboshow
相关产品推荐
相关产品推荐

