使用给定的时间和重新分析或插值重新采样时间序列

时间:2016-11-01 17:32:31

标签: pandas time-series interpolation timedelta binning

我有一个简单的时间序列,由日期时间值驱动(即,它定期记录数据点),Series1

datetime,temp
2015-05-28 17:00:00,24.199
2015-05-28 17:15:00,24.465
2015-05-28 17:30:00,24.392
2015-05-28 17:45:00,25.094
2015-05-28 18:00:00,25.239
etc.

我试图协调第二个时间序列,它由事件驱动(表示为二进制值0和1),Series2

datetime,window   
2015-05-28 17:00:00,0.0
2015-05-28 17:55:28,1.0
2015-06-08 07:35:31,0.0
2015-06-08 08:04:30,1.0
2015-06-18 17:11:55,0.0
2015-06-18 18:11:52,1.0
2015-06-19 18:14:09,0.0
etc.

我想协调两者,即将事件驱动的时间序列表示为每小时(或每小时)的值。 我假设这可能需要为Series2创建一个可以匹配Series1的日期时间索引,并使用[0,1]的值填充窗口列。这些值将来自某种“时间分级”,其中计算每个时间间隔中花费的时间百分比(时间间隔由Series1中后续行之间的日期时间差异定义。)

希望这是有道理的。

我尝试过使用不同方法重新取样,即 series2_hr = series2.resample('H').bfill()并尝试使用.mean.last,但这些都没有给我所需的输出。

我也试过插值:

series2_hr = series2.resample('H')
series2_hr = series2_hr.interpolate(method='time')

但又没有运气。

所需的输出是窗口值为1的给定时间间隔(例如每小时)的百分比。换句话说,该小时的窗口平均值(从0到1)。

示例:series2

datetime,window   
2015-05-28 17:00:00,0.0
2015-05-28 17:55:28,1.0
2015-06-08 07:35:31,0.0
2015-06-08 08:04:30,1.0
2015-06-18 17:11:55,0.0
2015-06-18 18:11:52,1.0
2015-06-19 18:14:09,0.0
etc.

应该转换为series2_reg:

2015-05-28 17:00:00,0.916 (=(17:55 - 17:00)/60)
2015-05-28 18:00:00,1
2015-05-28 19:00:00,1
...
2015-06-08 07:00:00,0.583 (=(07:35 - 07:00)/60))
2015-06-08 08:00:00,0.06 (=(08:04 - 08:00)/60))
2015-06-08 09:00:00,1
2015-06-08 10:00:00,1
...

1 个答案:

答案 0 :(得分:1)

import io
import pandas as pd

data = io.StringIO('''\
datetime,window   
2015-05-28 17:00:00,0.0
2015-05-28 17:55:28,1.0
2015-06-08 07:35:31,0.0
2015-06-08 08:04:30,1.0
2015-06-18 17:11:55,0.0
2015-06-18 18:11:52,1.0
2015-06-19 18:14:09,0.0
''')

s = pd.read_csv(data).set_index('datetime').squeeze()
s.index = pd.to_datetime(s.index)

从上采样到一分钟的间隔开始,向前填充原始时间序列的条目。

upsampled = s.resample('min').ffill()
upsampled['2015-06-08 07:30':'2015-06-08 08:10']

# datetime
# 2015-06-08 07:30:00    1.0
# 2015-06-08 07:31:00    1.0
# 2015-06-08 07:32:00    1.0
# 2015-06-08 07:33:00    1.0
# 2015-06-08 07:34:00    1.0
# 2015-06-08 07:35:00    1.0
# 2015-06-08 07:36:00    0.0
# 2015-06-08 07:37:00    0.0
# 2015-06-08 07:38:00    0.0
# 2015-06-08 07:39:00    0.0
# 2015-06-08 07:40:00    0.0
# 2015-06-08 07:41:00    0.0
# 2015-06-08 07:42:00    0.0
# 2015-06-08 07:43:00    0.0
# 2015-06-08 07:44:00    0.0
# 2015-06-08 07:45:00    0.0
# 2015-06-08 07:46:00    0.0
# 2015-06-08 07:47:00    0.0
# 2015-06-08 07:48:00    0.0
# 2015-06-08 07:49:00    0.0
# 2015-06-08 07:50:00    0.0
# 2015-06-08 07:51:00    0.0
# 2015-06-08 07:52:00    0.0
# 2015-06-08 07:53:00    0.0
# 2015-06-08 07:54:00    0.0
# 2015-06-08 07:55:00    0.0
# 2015-06-08 07:56:00    0.0
# 2015-06-08 07:57:00    0.0
# 2015-06-08 07:58:00    0.0
# 2015-06-08 07:59:00    0.0
# 2015-06-08 08:00:00    0.0
# 2015-06-08 08:01:00    0.0
# 2015-06-08 08:02:00    0.0
# 2015-06-08 08:03:00    0.0
# 2015-06-08 08:04:00    0.0
# 2015-06-08 08:05:00    1.0
# 2015-06-08 08:06:00    1.0
# 2015-06-08 08:07:00    1.0
# 2015-06-08 08:08:00    1.0
# 2015-06-08 08:09:00    1.0
# 2015-06-08 08:10:00    1.0
# Freq: T, Name: window   , dtype: float64

然后按小时重新取样,取每个间隔的平均值。

result = upsampled.resample('H').mean()
result['2015-06-08 06:00':'2015-06-08 09:00']

# datetime
# 2015-06-08 06:00:00    1.000000
# 2015-06-08 07:00:00    0.600000
# 2015-06-08 08:00:00    0.916667
# 2015-06-08 09:00:00    1.000000
# Freq: H, Name: window   , dtype: float64

请注意,上采样分配给具有该事件值的事件的分钟。如果您的事件数据表示开启和关闭,则表示upsampled中的每分钟都具有该时间段结束时该开/关开关的状态。这就是为什么我的数字与你的数字不完全相符(另外,我认为你在2015-06-08 08:00:00的计算中有错误。)

由于您的事件的粒度低至秒,您可以按秒而不是按分钟进行上述上采样,从而获得window的每小时平均值的更精确值。

upsampled = s.resample('s').ffill()
result = upsampled.resample('H').mean()
result['2015-06-08 06:00':'2015-06-08 09:00']

# datetime
# 2015-06-08 06:00:00    1.000000
# 2015-06-08 07:00:00    0.591944
# 2015-06-08 08:00:00    0.925000
# 2015-06-08 09:00:00    1.000000
# Freq: H, Name: window   , dtype: float64