Pandas 用 NaN 描述 vs scipy.stats percentileofscore?

Bri*_*tow 0 python scipy percentile pandas

我遇到了一个奇怪的情况,pd.describe 给我的百分位标记与 scipy.stats percentileofscore 不一致,我认为是因为 NaN。

我的 df 是:

      f_recommend
0     3.857143
1     4.500000
2     4.458333
3          NaN
4     3.600000
5          NaN
6     4.285714
7     3.587065
8     4.200000
9          NaN
Run Code Online (Sandbox Code Playgroud)

当我跑步时df.describe(percentiles=[.25, .5, .75])我得到:

       f_recommend
count     7.000000
mean      4.069751
std       0.386990
min       3.587065
25%       3.728571
50%       4.200000
75%       4.372024
max       4.500000
Run Code Online (Sandbox Code Playgroud)

当我删除 NaN 运行时,我得到相同的值。

然而,当我想查找特定值时,当我运行时,scipy.stats.percentileofscore(df['f_recommend'], 3.61, kind = 'mean')我得到:第 28 个百分位数包含 NaN,第 20 个百分位数不包含 NaN。

有什么想法可以解释这种差异吗?

预计到达时间:

我不认为问题在于我们计算百分位数的方式不同。因为只有当您以不同的方式计算相同的两个数字的百分位数时,这才重要。但在这里,describe 给出的 25 个百分位为 3.72。所以 3.61 绝对不可能是第 28 个百分位。没有一个公式可以给出这一点。

特别是,当我对不带 NaN 的 6 个值使用描述时,我得到相同的值,因此忽略 NaN,这很好。但是当我在没有 NaN 的情况下运行分数百分位时,我得到一个不匹配的数字。

预计到达时间 2:

更简单的例子:

In [48]: d = pd.DataFrame([1,2,3,4,5,6,7])

In [49]: d.describe()
Out[49]: 
              0
count  7.000000
mean   4.000000
std    2.160247
min    1.000000
25%    2.500000
50%    4.000000
75%    5.500000
max    7.000000

In [50]: sp.stats.percentileofscore(d[0], 2.1, kind = 'mean')
Out[50]: 28.571428571428573
Run Code Online (Sandbox Code Playgroud)

“kind”参数并不重要,因为 2.1 是唯一的。

War*_*ser 5

scipy.stats.percentileofscore不忽略nan,也不检查该值并以某种特殊方式处理它。它只是数据中的另一个浮点值。percentileofscore这意味着with data contains的行为是未定义的,因为in 比较nan的行为:nan

In [44]: np.nan > 0
Out[44]: False

In [45]: np.nan < 0
Out[45]: False

In [46]: np.nan == 0
Out[46]: False

In [47]: np.nan == np.nan
Out[47]: False
Run Code Online (Sandbox Code Playgroud)

这些结果都是正确的——这就是nan应该的行为方式。但这意味着,为了知道如何percentileofscore处理nan,您必须知道代码如何进行比较。这是您不必知道的实现细节,并且您不能依赖它在 scipy 的未来版本中相同。

如果您研究 的行为percentfileofscore,您会发现它的行为就像nan是无限的。例如,如果您替换nan为大于输入中任何其他值的值,您将得到相同的结果:

In [53]: percentileofscore([10, 20, 25, 30, np.nan, np.nan], 18)
Out[53]: 16.666666666666664

In [54]: percentileofscore([10, 20, 25, 30, 999, 999], 18)
Out[54]: 16.666666666666664
Run Code Online (Sandbox Code Playgroud)

不幸的是,您不能依赖这种行为。如果将来实现发生变化,最终nan可能会表现得像负无穷大,或者有其他一些未指定的行为。

这个“问题”的解决方案很简单:不要给出percentileofscore任何nan值。您必须先清理数据。请注意,这可以很简单:

result = percentileofscore(a[~np.isnan(a)], score)
Run Code Online (Sandbox Code Playgroud)