【问题标题】:Fastest way to get rolling averages in pandas?获得熊猫滚动平均值的最快方法?
【发布时间】:2018-04-05 21:18:14
【问题描述】:

我有一个节点列表(其中大约 2300 个),其中包含大约一年的每小时价格数据。我有一个脚本,对于每个节点,循环遍历一天中的时间以创建 4 小时的追踪平均值,然后按月和小时对平均值进行分组。最后,对一个月中的这些时间进行平均,得出每个月的典型价格日。我想知道是否有更快的方法来做到这一点,因为我所拥有的似乎需要大量时间(大约一个小时)。我还将数据框保存为 csv 文件以供以后可视化(这不是慢速部分)。

df (before anything is done to it)
        Price_Node_Name      Local_Datetime_HourEnding   Price      Irrelevant_column

0       My-node                 2016-08-17 01:00:00        20.95          EST
1       My-node                 2016-08-17 02:00:00        21.45          EST
2       My-node                 2016-08-17 03:00:00        25.60          EST

df_node (after the groupby as it looks going to csv)
Month        Hour             MA
1            0                23.55
1            1                23.45
1            2                21.63


 for node in node_names:
     df_node = df[df['Price_Node_Name'] == node]
     df_node['MA'] = df_node['Price'].rolling(4).mean()
     df_node = df_node.groupby([df_node['Local_Datetime_HourEnding'].dt.month, 
                      df_node['Local_Datetime_HourEnding'].dt.hour]).mean()
     df_node.to_csv('%s_rollingavg.csv' % node)

我收到一个关于 SetWithCopy 的弱错误警告我,但我还没有完全弄清楚如何在此处使用 .loc,因为列 ['MA'] 不存在,直到我在此 sn-p 和任何我能想到的方法是事先创建它并填充它似乎比我拥有的要慢。虽然可能是完全错误的。任何帮助都会很棒。

python 3.6

【问题讨论】:

  • 显示一些数据的剪切和粘贴如何?
  • 我在滚动平均和每小时平均之前和之后添加了几行示例数据。
  • 你试过rolling_meanSeries.rolling吗?
  • 我认为大多数使用Pandas 的人都会同意“如果你使用循环,那么你做错了”的说法。至少,这种情绪对我学习在Pandas 中找到更有效的解决方案非常有帮助。

标签: python pandas loops


【解决方案1】:

编辑:我可能误读了这里的问题,希望这至少能激发一些解决方案的想法。

我认为在 Pandas 中处理时间序列数据时,将索引作为日期时间列很有用。

这里是一些示例数据:

Out[3]:
                          price
date
2015-01-14 00:00:00  155.427361
2015-01-14 01:00:00  205.285202
2015-01-14 02:00:00  205.305021
2015-01-14 03:00:00  195.000000
2015-01-14 04:00:00  213.102000
2015-01-14 05:00:00  214.500000
2015-01-14 06:00:00  222.544375
2015-01-14 07:00:00  227.090251
2015-01-14 08:00:00  227.700000
2015-01-14 09:00:00  243.456190

我们使用Series.rolling 创建一个MA 列,即我们将该方法应用于price 列,具有两个周期的窗口,并在生成的rolling 对象上调用mean

In [4]: df['MA'] = df.price.rolling(window=2).mean()

In [5]: df
Out[5]:
                          price          MA
date
2015-01-14 00:00:00  155.427361         NaN
2015-01-14 01:00:00  205.285202  180.356281
2015-01-14 02:00:00  205.305021  205.295111
2015-01-14 03:00:00  195.000000  200.152510
2015-01-14 04:00:00  213.102000  204.051000
2015-01-14 05:00:00  214.500000  213.801000
2015-01-14 06:00:00  222.544375  218.522187
2015-01-14 07:00:00  227.090251  224.817313
2015-01-14 08:00:00  227.700000  227.395125
2015-01-14 09:00:00  243.456190  235.578095

如果你想要monthhour 列,可以从索引中提取它们:

In [7]: df['month'] = df.index.month  

In [8]: df['hour'] = df.index.hour

In [9]: df
Out[9]:
                          price          MA  month  hour
date
2015-01-14 00:00:00  155.427361         NaN      1     0
2015-01-14 01:00:00  205.285202  180.356281      1     1
2015-01-14 02:00:00  205.305021  205.295111      1     2
2015-01-14 03:00:00  195.000000  200.152510      1     3
2015-01-14 04:00:00  213.102000  204.051000      1     4
2015-01-14 05:00:00  214.500000  213.801000      1     5
2015-01-14 06:00:00  222.544375  218.522187      1     6
2015-01-14 07:00:00  227.090251  224.817313      1     7
2015-01-14 08:00:00  227.700000  227.395125      1     8
2015-01-14 09:00:00  243.456190  235.578095      1     9

那么我们可以使用groupby:

In [11]: df.groupby([
    ...:     df['month'],
    ...:     df['hour']
    ...: ]).mean()[['MA']]
Out[11]:
                    MA
month hour
1     0            NaN
      1     180.356281
      2     205.295111
      3     200.152510
      4     204.051000
      5     213.801000
      6     218.522187
      7     224.817313
      8     227.395125
      9     235.578095

【讨论】:

  • 他在这里使用Series.rolling()df_node['Price'].rolling(4).mean()
  • 是的,这就是我正在做的事情。虽然在这里做滚动平均值在技术上更准确,因为它滚动到午夜,而我所拥有的,或者在每月每小时平均后停止在午夜停止并在第二天再次开始滚动。
【解决方案2】:

这里有一些事情可以尝试:

将 'Price_Node_name' 设置为循环前的索引

df.set_index('Price_Node_name', inplace=True)
for node in node_names:
    df_node = df[node]

在 groupby 中使用 sort=False 作为 kwarg

df_node.groupby(..., sort=False).mean()

在 groupby 之后执行滚动平均,或者根本不执行 - 我认为您的情况不需要它。平均一个月的小时总数将为您提供典型一天的预期值,这是您想要的。如果您仍需要滚动平均值,请在每个月的平均小时总数上执行它。

【讨论】:

  • 我被代码迷住了,以至于我没有仔细考虑统计数据!如果我需要的话,肯定会在每月平均后做一个滚动平均。将报告两个建议的速度。
猜你喜欢
  • 2015-09-11
  • 2019-07-27
  • 2020-04-23
  • 2017-08-27
  • 2023-02-17
  • 2020-03-26
  • 1970-01-01
  • 2018-04-26
相关资源
最近更新 更多