【问题标题】:Unexpected result from rolling window function when using offset使用偏移量时滚动窗口函数的意外结果
【发布时间】:2021-10-02 07:34:09
【问题描述】:

我有一个看起来像这样的数据框

                     ACCEL_X  ACCEL_Y  ACCEL_Z
DATETIME                                      
2021-05-11 16:12:56      160       32    16392
2021-05-11 16:12:57       20     -192    16548
2021-05-11 16:12:57      128      224    16212
2021-05-11 16:12:57     -148     -132    16624
2021-05-11 16:12:57      -40      204    16132
2021-05-11 16:12:57       72     -132    16536
2021-05-11 16:12:57      220       48    16292
2021-05-11 16:12:57     -132      236    16332
2021-05-11 16:12:57     -232     -132    16628
2021-05-11 16:12:57      192      140    16172
2021-05-11 16:12:57      200      -96    16684
2021-05-11 16:12:57        0       64    16020
2021-05-11 16:12:57     -144      -24    16524
2021-05-11 16:12:57     -160       24    16336
2021-05-11 16:12:57       96       56    16252
2021-05-11 16:12:57       68      -44    16544
2021-05-11 16:12:57       12       76    16308
2021-05-11 16:12:57     -228     -132    16668
2021-05-11 16:12:57       72      -96    16244
2021-05-11 16:12:57       48      -96    16536

根据documentation,我可以使用第二个执行滑动窗口,并且我已经使用代码执行了3s的滑动窗口滚动:

df = df.rolling('3s').mean()
df

返回,

                        ACCEL_X    ACCEL_Y       ACCEL_Z
DATETIME                                                
2021-05-11 16:12:56  160.000000  32.000000  16392.000000
2021-05-11 16:12:57   90.000000 -80.000000  16470.000000
2021-05-11 16:12:57  102.666667  21.333333  16384.000000
2021-05-11 16:12:57   40.000000 -17.000000  16444.000000
2021-05-11 16:12:57   24.000000  27.200000  16381.600000
2021-05-11 16:12:57   32.000000   0.666667  16407.333333
2021-05-11 16:12:57   58.857143   7.428571  16390.857143
2021-05-11 16:12:57   35.000000  36.000000  16383.500000
2021-05-11 16:12:57    5.333333  17.333333  16410.666667
2021-05-11 16:12:57   24.000000  29.600000  16386.800000
2021-05-11 16:12:57   40.000000  18.181818  16413.818182
2021-05-11 16:12:57   36.666667  22.000000  16381.000000
2021-05-11 16:12:57   22.769231  18.461538  16392.000000
2021-05-11 16:12:57    9.714286  18.857143  16388.000000
2021-05-11 16:12:57   15.466667  21.333333  16378.933333
2021-05-11 16:12:57   18.750000  17.250000  16389.250000
2021-05-11 16:12:57   18.352941  20.705882  16384.470588
2021-05-11 16:12:57    4.666667  12.222222  16400.222222
2021-05-11 16:12:57    8.210526   6.526316  16392.000000
2021-05-11 16:12:57   10.200000   1.400000  16399.200000

当我在滑动窗口后打印 df 时引起了我的注意,它返回了不同的期望结果。

据我对滑动窗口的了解,它应该需要 'N 秒,在我的情况下为 3s' 间隔数据,并从中执行平均值。

就我所见,“日期时间”完全相同,它应该返回相同的结果。但事实并非如此,谁能告诉我 pandas 的滑动窗口是如何工作的?

--- 编辑 1 ---

运行

df.index.inferred_type == "datetime64"

返回

True

【问题讨论】:

  • 我查过是datetimeindex,误会了,我只跑过一次3s。关于三元运行均值,在我计算了几个值之后,它也不匹配。
  • 是的,我已经检查了您的示例,可以重现该问题(pandas v1.3.0)。我的 猜测 如果您的 DatetimeIndex 的总时间窗口跨度小于指定时间段,那么 pandas 会退回到简单的元素平均。无论如何,这种极端情况似乎没有得到充分记录(根本没有......)。

标签: python pandas datetime


【解决方案1】:

您的三秒窗口涵盖了所有数据点。您可以看到结果中的最后一行是整个 DataFrame 的平均值。也许你已经预料到了:

In [194]: df.rolling('3s', center=True).mean()
Out[194]:
                     ACCEL_X  ACCEL_Y  ACCEL_Z
DATETIME
2021-05-11 16:12:56     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2
2021-05-11 16:12:57     10.2      1.4  16399.2

来自documentation:“默认情况下,结果设置在窗口的右边缘。可以通过设置center=True将其更改为窗口的中心。”

center=False 第一个元素处的窗口仅覆盖该元素时,在第二个元素处它覆盖第一个和第二个元素,依此类推。在最后一个元素处,它覆盖了所有元素,因为窗口已扩展为覆盖当前元素后三秒的所有元素。当center=True 时,窗口的中心依次放置在每个元素上。此窗口将覆盖当前元素以及落后一秒和前一秒的所有元素。我仍然怀疑当偏移量是偶数时会发生什么,例如'2s'和center=True

看看当我在 2021-05-11 16:12:58 添加另一个数据点时会发生什么。这里我使用 count 聚合来更好地说明:

In [214]: df3.rolling('3s', center=True).count()
Out[214]:
                     ACCEL_X  ACCEL_Y  ACCEL_Z
DATETIME
2021-05-11 16:12:56     20.0     20.0     20.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:57     21.0     21.0     21.0
2021-05-11 16:12:58     20.0     20.0     20.0

这里的关键见解是,窗口会根据有多少元素落在指定的偏移量内而改变其大小并且也会在数据中滚动(因为它是滚动窗口)。 center 参数控制窗口相对于每个数据点的跨度。


编辑:pandas 错误(在 1.3.2 中修复)

pandas 1.3.1 在这个答案中给出了不一致的代码结果。在这种情况下,输出的第一行会出现不一致,有时是:

                     ACCEL_X  ACCEL_Y  ACCEL_Z
DATETIME
2021-05-11 16:12:56    160.0     32.0  16392.0

也就是说,第一行有时是自己占用的。正确的结果如上图所示。这已在 1.3.2 版中修复,并记录在问题 #42753 中。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2018-10-29
  • 1970-01-01
  • 2021-03-02
  • 1970-01-01
  • 2015-06-25
  • 2019-11-08
  • 2018-07-29
  • 1970-01-01
相关资源
最近更新 更多