我有一个节点列表(大约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
答案 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
如果您想要month
和hour
列,可以从索引中提取这些列:
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()
在群组之后执行滚动平均值,或者根本不执行滚动平均值 - 在您的情况下我认为您不需要它。平均每小时总计一个月将为您提供典型日期的预期值,这是您所希望的。如果您仍想要滚动平均值,请按每月的平均每小时总计执行。