我正在查看有关窗口函数的教程,但我不太明白为什么下面的代码会生成NaN。
如果我理解正确,代码会创建一个大小为2的滚动窗口。为什么第一行,第四行和第五行都有NaN?起初,我认为这是因为添加NaN与另一个数字会产生NaN,但是我不知道为什么第二行不会是NaN。
dft = pd.DataFrame({'B': [0, 1, 2, np.nan, 4]},
index=pd.date_range('20130101 09:00:00', periods=5, freq='s'))
In [58]: dft.rolling(2).sum()
Out[58]:
B
2013-01-01 09:00:00 NaN
2013-01-01 09:00:01 1.0
2013-01-01 09:00:02 3.0
2013-01-01 09:00:03 NaN
2013-01-01 09:00:04 NaN
答案 0 :(得分:13)
首先要注意的是,默认情况下rolling
查找要汇总的n-1个先前数据行,其中n是窗口大小。如果不满足该条件,它将返回窗口的NaN。这就是第一行发生的事情。在第四和第五行,这是因为总和中的一个值是NaN。
如果您想避免返回NaN,可以将min_periods=1
传递给方法,该方法会将窗口中有效观察所需的最小数量减少到1而不是2:
>>> dft.rolling(2, min_periods=1).sum()
B
2013-01-01 09:00:00 0.0
2013-01-01 09:00:01 1.0
2013-01-01 09:00:02 3.0
2013-01-01 09:00:03 2.0
2013-01-01 09:00:04 4.0
答案 1 :(得分:0)
确实添加NAN和其他任何东西都会给NAN。所以:
input + rolled = sum
0 nan nan
1 0 1
2 1 3
nan 2 nan
4 nan nan
第二行没有理由是NAN,因为它是原始第一和第二元素的总和,两者都不是NAN。
另一种方法是:
dft.B + dft.B.shift()
答案 2 :(得分:0)
使用rolling('2d')而不是rolling(2)
dft = pd.DataFrame({'B': [0, 1, 2, np.nan, 4]},
index=pd.date_range('20130101 09:00:00', periods=5, freq='s'))
dft.rolling('2d').sum()
答案 3 :(得分:0)
使用 min_periods=1
会导致滚动窗口中的值出现高方差。删除 NaN
值的另一种方法是在滚动窗口上使用 fillna
:
>>> dft.rolling(2).sum().fillna(method='bfill').fillna(method='ffill')
B
2013-01-01 09:00:00 1.0
2013-01-01 09:00:01 1.0
2013-01-01 09:00:02 3.0
2013-01-01 09:00:03 3.0
2013-01-01 09:00:04 3.0
滚动窗口大小为 6 的示例说明了该问题:
>>> dft = pd.DataFrame({'B': [10, 1, 10, 1, 10, 1, 10, 1, 10, 1]}, index=pd.date_range('20130101 09:00:00', periods=10, freq='s'))
>>> dft.rolling(6, min_periods=1).sum()
B
2013-01-01 09:00:00 10.0
2013-01-01 09:00:01 11.0
2013-01-01 09:00:02 21.0
2013-01-01 09:00:03 22.0
2013-01-01 09:00:04 32.0
2013-01-01 09:00:05 33.0
2013-01-01 09:00:06 33.0
2013-01-01 09:00:07 33.0
2013-01-01 09:00:08 33.0
2013-01-01 09:00:09 33.0
>>> dft.rolling(6).sum().fillna(method='bfill')
B
2013-01-01 09:00:00 33.0
2013-01-01 09:00:01 33.0
2013-01-01 09:00:02 33.0
2013-01-01 09:00:03 33.0
2013-01-01 09:00:04 33.0
2013-01-01 09:00:05 33.0
2013-01-01 09:00:06 33.0
2013-01-01 09:00:07 33.0
2013-01-01 09:00:08 33.0
2013-01-01 09:00:09 33.0
虽然使用 min_periods=1
会导致前 5 个值低于 33.0,但使用 fillna
会在整个窗口中产生预期的 33.0。根据您的用例,您可能希望使用 fillna
。