熊猫滚动给NaN

时间:2016-11-26 01:53:45

标签: python pandas

我正在查看有关窗口函数的教程,但我不太明白为什么下面的代码会生成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

4 个答案:

答案 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

相关问题