pandas.DataFrame.describe() 与 numpy.percentile() NaN 处理
Posted
技术标签:
【中文标题】pandas.DataFrame.describe() 与 numpy.percentile() NaN 处理【英文标题】:pandas.DataFrame.describe() vs numpy.percentile() NaN handling 【发布时间】:2014-01-04 01:22:21 【问题描述】:我注意到 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 值的时间序列并且想要重新采样到百分位数(每 this post)
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),它可以扭曲统计数据。这是我的担心。
结束编辑
【问题讨论】:
你当然可以向 numpy 提出功能请求;他们有专门的 nan 处理方法,例如nanmean,nansum
,所以我怀疑这是必要的。改用熊猫!
这些天我更喜欢熊猫。但是,这在重新采样数据时成为一个问题,例如见上面的编辑。
nan 处理将以性能为代价进行。 np.percentile(a[~np.isnan(a)], [25,50,75])
【参考方案1】:
对于您编辑的用例,我想我会留在pandas
并使用Series.quantile
而不是np.percentile
:
>>> df = pd.DataFrame(np.random.rand(100000),columns=['A'],
... index=pd.date_range("Jan 1 2013", freq="H", periods=100000))
>>> df.iloc[1:99999:3] = np.nan
>>>
>>> upper_np = df.resample('1A',how=lambda x: np.percentile(x,q=75))
>>> upper_np.describe()
A
count 0
mean NaN
std NaN
min NaN
25% NaN
50% NaN
75% NaN
max NaN
[8 rows x 1 columns]
>>> upper_pd = df.resample('1A',how=lambda x: x.quantile(0.75))
>>> upper_pd.describe()
A
count 12.000000
mean 0.745648
std 0.004889
min 0.735160
25% 0.744723
50% 0.747492
75% 0.748965
max 0.750341
[8 rows x 1 columns]
【讨论】:
以上是关于pandas.DataFrame.describe() 与 numpy.percentile() NaN 处理的主要内容,如果未能解决你的问题,请参考以下文章
pandas.DataFrame.describe() 在 .py 脚本中没有输出
pandas.DataFrame.describe 官方文档翻译percentile_width,percentiles,include, exclude