我有一些时间序列数据作为Pandas数据框,它从每小时的15分钟和45分钟(30分钟的时间间隔)开始观察,然后将频率更改为每分钟。我想对数据进行重新采样,以使整个数据帧的正常频率为每30分钟一次,在过去15点和每小时45点之后。
我想到了两种实现方法。
1.使用时间序列数据作为数据框中的一列,只需在15min和45min时对所有观察数据进行过滤即可。
2.重新设置索引,使时间序列数据成为多索引的一部分(索引的第0层是气象站,第1层是观测时间),并使用Pandas日期时间序列功能,例如resample()
。
原始数据帧(天气)如下所示:
parsed_time Pressure Temp Hum
Station (index)
Bow 1 2018-04-15 14:15:00 1012 20.0 87
2 2018-04-15 14:45:00 1013 20.0 87
3 2018-04-15 15:15:00 1012 21.0 87
4 2018-04-15 15:45:00 1014 22.0 86
5 2018-04-15 16:00:00 1015 22.0 86
6 2018-04-15 16:01:00 1012 25.0 86
7 2018-04-15 16:02:00 1012 25.0 86
Stratford 8 2018-04-15 14:15:00 1011 18.0 87
9 2018-04-15 14:45:00 1011 18.0 87
10 2018-04-15 15:15:00 1012 18.0 87
11 2018-04-15 15:45:00 1014 19.0 86
12 2018-04-15 16:00:00 1014 19.0 86
13 2018-04-15 16:01:00 1015 19.0 86
14 2018-04-15 16:02:00 1016 20.0 86
15 2018-04-15 16:04:00 1016 20.0 86
使用方法1,我的问题是我的布尔选择操作似乎无法按预期工作。例如
weather_test = weather[weather['parsed_time'].dt.minute == (15 & 45)]
给出如下的parsed_time值:
2018-04-15 14:13:00
2018-04-15 15:13:00
weather_test = weather[weather['parsed_time'].dt.minute == (15 | 45)]
产生如下的parsed_time值:
2018-04-15 14:47:00
2018-04-15 14:47:00
我在文档中找不到任何可以解释这种行为的内容。我想要的是在以下时间按站的压力,温度,湿度:
2018-04-15 14:45:00
2018-04-15 15:15:00
2018-04-15 15:45:00
2018-04-15 16:15:00
以此类推。
使用方法2,我想到了对数据进行重新采样,以便将具有我的每一分钟数据的观测值替换为前30分钟的平均值。仅当parsed_time列是索引的一部分时,此功能才似乎起作用。因此,我使用以下代码将parsed_time设置为多索引的一部分:
weather.set_index('parsed_time', append=True, inplace=True)
weather.index.set_names('station', level=0, inplace=True)
weather = weather.reset_index(level=1, drop=True)
最后得到一个看起来像这样的数据框:
Pressure Temp Hum
Station parsed_time
Bow 2018-04-15 14:15:00 1012 20.0 87
2018-04-15 14:45:00 1013 20.0 87
2018-04-15 15:15:00 1012 21.0 87
2018-04-15 15:45:00 1014 22.0 86
2018-04-15 16:00:00 1015 22.0 86
2018-04-15 16:01:00 1012 25.0 86
2018-04-15 16:02:00 1012 25.0 86
Stratford 2018-04-15 14:15:00 1011 18.0 87
2018-04-15 14:45:00 1011 18.0 87
2018-04-15 15:15:00 1012 18.0 87
2018-04-15 15:45:00 1014 19.0 86
2018-04-15 16:00:00 1014 19.0 86
2018-04-15 16:01:00 1015 19.0 86
2018-04-15 16:02:00 1016 20.0 86
2018-04-15 16:04:00 1016 20.0 86
请注意,观测值的采样范围从过去的15:30和过去的45:30每分钟(例如:01,:02,:14等)有所不同,而且每个站点也有所不同-并非所有站点都有每次观察。
我尝试过:
weather_test = weather.resample('30min', level=1).mean()
但是这将重新采样而没有偏移,并且也摆脱了多索引中的电台水平。
期望的结果是这样
Pressure Temp Hum
Station parsed_time
Bow 2018-04-15 14:15:00 1012 20.0 87
2018-04-15 14:45:00 1013 20.0 87
2018-04-15 15:15:00 1012 21.0 87
2018-04-15 15:45:00 1014 22.0 86
2018-04-15 16:15:00 1013 24.0 86
Stratford 2018-04-15 14:15:00 1011 18.0 87
2018-04-15 14:45:00 1011 18.0 87
2018-04-15 15:15:00 1012 18.0 87
2018-04-15 15:45:00 1014 19.0 86
2018-04-15 16:15:00 1015 19.5 86
每分钟的分钟观测值已重新采样,以30分钟间隔的平均值在每小时的15分和45分之间进行采样。
将工作站保持在多索引级别是必不可少的。我不能单独使用时间索引作为索引,因为每个站的值都重复(而且不是唯一的)。
感谢所有帮助,因为我现在已经与这个圈子转了一圈了。谢谢!
我看过很多以前的文章,包括:
Boolean filter using a timestamp value on a dataframe in Python
How do I round datetime column to nearest quarter hour
和:Resampling a pandas dataframe with multi-index containing timeseries
对于应该很简单的东西来说似乎有点复杂...
和文档:http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.resample.html 谢谢!
答案 0 :(得分:2)
从倒数第二个数据帧开始(使用weather.reset_index(Station, inplace=True)
之后):
Station Pressure Temp Hum
parsed_time
2018-04-15 14:15:00 Bow 1012.0 20.0 87.0
2018-04-15 14:45:00 Bow 1013.0 20.0 87.0
2018-04-15 15:15:00 Bow 1012.0 21.0 87.0
2018-04-15 15:45:00 Bow 1014.0 22.0 86.0
2018-04-15 16:00:00 Bow 1015.0 22.0 86.0
2018-04-15 16:01:00 Bow 1012.0 25.0 86.0
2018-04-15 16:02:00 Bow 1012.0 25.0 86.0
2018-04-15 14:15:00 Stratford 1011.0 18.0 87.0
2018-04-15 14:45:00 Stratford 1011.0 18.0 87.0
2018-04-15 15:15:00 Stratford 1012.0 18.0 87.0
2018-04-15 15:45:00 Stratford 1014.0 19.0 86.0
2018-04-15 16:00:00 Stratford 1014.0 19.0 86.0
2018-04-15 16:01:00 Stratford 1015.0 19.0 86.0
2018-04-15 16:02:00 Stratford 1016.0 20.0 86.0
2018-04-15 16:04:00 Stratford 1016.0 20.0 86.0
您可以结合使用groupby
和resample
:
res = weather.groupby('Station').resample('30min').mean().reset_index('Station')
默认情况下,resample
选择合并间隔[16:00, 16:30)
和[16:30, 17:00)
。正如您已经注意到的那样,时间索引是在没有偏移的情况下重新采样的,但是您可以在以后使用DateOffset
将其重新添加:
res.index = res.index + pd.DateOffset(minutes=15)
产生:
Station Pressure Temp Hum
parsed_time
2018-04-15 14:15:00 Bow 1012.00 20.0 87.0
2018-04-15 14:45:00 Bow 1013.00 20.0 87.0
2018-04-15 15:15:00 Bow 1012.00 21.0 87.0
2018-04-15 15:45:00 Bow 1014.00 22.0 86.0
2018-04-15 16:15:00 Bow 1013.00 24.0 86.0
2018-04-15 14:15:00 Stratford 1011.00 18.0 87.0
2018-04-15 14:45:00 Stratford 1011.00 18.0 87.0
2018-04-15 15:15:00 Stratford 1012.00 18.0 87.0
2018-04-15 15:45:00 Stratford 1014.00 19.0 86.0
2018-04-15 16:15:00 Stratford 1015.25 19.5 86.0
或者,您可以直接在重采样方法中指定偏移量:
weather.groupby('Station').resample('30min', loffset=pd.Timedelta('15min')).mean()
答案 1 :(得分:1)
我没有您的数据,因此我无法直接检查此数据,但是请对您称为选项1的选项尝试以下语法:
weather_test = weather[(weather['parsed_time'].dt.minute == 15) | (weather['parsed_time'].dt.minute == 45)]
答案 2 :(得分:1)
如果您开始时没有任何索引(行索引除外),则可以执行以下操作:
# Create a rounded timestamp
df['parsed_time_rounded'] = (df['parsed_time'] - pd.Timedelta('15min')).dt.round('30min') + pd.Timedelta('15min')
# Group by the station, and the rounded timestamp instead of the raw timestamp
df.groupby(['Station', 'parsed_time_rounded']).mean()