我注意到 pandas.DataFrame.describe() 和 numpy.percentile() 处理 NaN 值的方式有所不同。例如
import numpy as np
import pandas as pd
a = pd.DataFrame(np.random.rand(100000),columns=['A'])
>>> a.describe()
A
count 100000.000000
mean 0.499713
std 0.288722
min 0.000009
25% 0.249372
50% 0.498889
75% 0.749249
max 0.999991
>>> np.percentile(a,[25,50,75])
[0.24937217017643742, 0.49888913303316823, 0.74924862428575034] # Same as a.describe()
# Add in NaN values
a.ix[1:99999:3] = pd.np.NaN
>>> a.describe()
A
count 66667.000000
mean 0.499698
std 0.288825
min 0.000031
25% 0.249285
50% 0.500110
75% 0.750201
max 0.999991
>>> np.percentile(a,[25,50,75])
[0.37341740173545901, 0.75020053461424419, nan] # Not the same as a.describe()
# Remove NaN's
b = a[pd.notnull(a.A)]
>>> np.percentile(b,[25,50,75])
[0.2492848255776256, 0.50010992119477615, 0.75020053461424419] # Now in agreement with describe()
Pandas 在百分位数计算中会忽略 NaN 值,而 numpy 不会。是否有任何令人信服的理由将 NaN 包含在百分位数计算中?看来 Pandas 正确地处理了这个问题,所以我想知道为什么 numpy 不会做出类似的实现。
开始编辑
根据 Jeff 的评论,这在重新采样数据时会成为一个问题。如果我有一个包含 NaN 值的时间序列并且想要重新采样到百分位数(根据这篇文章)
upper = df.resample('1A',how=lambda x: np.percentile(x,q=75))
将在计算中包含 NaN 值(就像 numpy 一样)。为避免这种情况,您必须改为放置
upper = tmp.resample('1A',how=lambda x: np.percentile(x[pd.notnull(x.sample_value)],q=75))
也许一个 numpy 请求是有序的。就个人而言,我认为没有任何理由将 NaN 包含在百分位数计算中。在我看来,pd.describe() 和 np.percentile 应该返回完全相同的值(我认为这是预期的行为),但是它们不容易被遗漏的事实(这在文档中没有提到) np.percentile),它可以扭曲统计数据。这是我的担忧。
结束编辑