在熊猫中获得滚动平均值的最快方法?

时间:2017-10-24 23:03:06

标签: python pandas loops

我有一个节点列表(大约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']不存在直到我在这个片段中创建它,我可以想到任何方式在手工创建它并填充它似乎比我有的慢。可能完全错了。任何帮助都会很棒。

python 3.6

2 个答案:

答案 0 :(得分: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列,并使用两个周期的窗口,然后调用mean生成rolling对象:

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

答案 1 :(得分:0)

以下是一些尝试:

将'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()

在群组之后执行滚动平均值,或者根本不执行滚动平均值 - 在您的情况下我认为您不需要它。平均每小时总计一个月将为您提供典型日期的预期值,这是您所希望的。如果您仍想要滚动平均值,请按每月的平均每小时总计执行。