熊猫滚动适用于nan



我无法理解pandas.rolling.applynp.prod和NaNs的行为。例如

import pandas as pd
import numpy as np
df = pd.DataFrame({'B': [1, 1, 2, np.nan, 4], 'C': [1, 2, 3, 4, 5]}, index=pd.date_range('2013-01-01', '2013-01-05'))

给出这个数据帧:

B   C
2013-01-01  1.0 1
2013-01-02  1.0 2
2013-01-03  2.0 3
2013-01-04  NaN 4
2013-01-05  4.0 5

如果我applynumpynp.prod函数到raw=Falsemin_periods=1的3天滚动窗口,它按预期工作,忽略nan。

df.rolling('3D', min_periods=1).apply(np.prod, raw=False)
B   C
2013-01-01  1.0 1.0
2013-01-02  1.0 2.0
2013-01-03  2.0 6.0
2013-01-04  2.0 24.0
2013-01-05  8.0 60.0

但是对于raw=True,我在B列中得到nan:

df.rolling('3D', min_periods=1).apply(np.prod, raw=True)
B   C
2013-01-01  1.0 1.0
2013-01-02  1.0 2.0
2013-01-03  2.0 6.0
2013-01-04  NaN 24.0
2013-01-05  NaN 60.0

我想使用raw=True的速度,但我不明白这种行为?有人能解释一下这是怎么回事吗?

这很简单。你可以试试下面的代码

import pandas as pd
import numpy as np

def foo(x):
return np.prod(x, where=~np.isnan(x))

if __name__ == '__main__':
df = pd.DataFrame({'B': [1, 1, 2, np.nan, 4], 'C': [1, 2, 3, 4, 5]},
index=pd.date_range('2013-01-01', '2013-01-05'))
res = df.rolling('3D', min_periods=1).apply(foo, raw=True)

print(res)
B     C
2013-01-01  1.0   1.0
2013-01-02  1.0   2.0
2013-01-03  2.0   6.0
2013-01-04  2.0  24.0
2013-01-05  8.0  60.0

感谢@padu和@bui提供的评论/答案,让我找到了我一直在寻找的答案,即解释不同的行为。

正如文档所指出的,当使用raw=False调用滚动apply时,每个窗口都被转换为熊猫。在传递给np.prod之前。使用raw=True,每个窗口被转换为numpy数组。

关键的观察是np.prod在Series和narray上的行为不同,忽略了Series中的NaN,这就是为什么我们得到不同的行为:

np.prod(np.array([1, 2, np.nan, 3]))给出nan

np.prod(pd.Series([1, 2, np.nan, 3]))给出6.0

我不清楚为什么NaN会被忽略,但正如@bui指出的那样,您可以通过将where关键字设置为np.prod来忽略narray情况下的NaN。

最新更新