确定Python中重叠时间序列的最有效方法

kli*_*lib 9 python performance time-series pandas pandas-groupby

我试图确定两个时间序列使用python的pandas库重叠的时间百分比.数据是非同步的,因此每个数据点的时间不对齐.这是一个例子:

时间序列1

2016-10-05 11:50:02.000734    0.50
2016-10-05 11:50:03.000033    0.25
2016-10-05 11:50:10.000479    0.50
2016-10-05 11:50:15.000234    0.25
2016-10-05 11:50:37.000199    0.50
2016-10-05 11:50:49.000401    0.50
2016-10-05 11:50:51.000362    0.25
2016-10-05 11:50:53.000424    0.75
2016-10-05 11:50:53.000982    0.25
2016-10-05 11:50:58.000606    0.75
Run Code Online (Sandbox Code Playgroud)

时间序列2

2016-10-05 11:50:07.000537    0.50
2016-10-05 11:50:11.000994    0.50
2016-10-05 11:50:19.000181    0.50
2016-10-05 11:50:35.000578    0.50
2016-10-05 11:50:46.000761    0.50
2016-10-05 11:50:49.000295    0.75
2016-10-05 11:50:51.000835    0.75
2016-10-05 11:50:55.000792    0.25
2016-10-05 11:50:55.000904    0.75
2016-10-05 11:50:57.000444    0.75
Run Code Online (Sandbox Code Playgroud)

假设系列保持其值直到下一次更改,确定它们具有相同值的时间百分比的最有效方法是什么?

例

让我们计算这些系列重叠的时间从11:50:07.000537开始,到2016-10-05 11:50:57.000444 0.75结束,因为我们有这个时期的两个系列的数据.有重叠的时间:

  • 11:50:10.000479 - 11:50:15.000234(两者的值均为0.5)4.999755秒
  • 11:50:37.000199 - 11:50:49.000295(两者的值均为0.5)12.000096秒
  • 11:50:53.000424 - 11:50:53.000982(均值为0.75)0.000558秒
  • 11:50:55.000792 - 11:50:55.000904(均值为0.25)0.000112秒

结果(4.999755 + 12.000096 + 0.000558 + 0.000112)/ 49.999907 = 34%

其中一个问题是我的实际时间序列有更多的数据,例如1000 - 10000个观测值,我需要运行更多对.我考虑过向前填充一个系列,然后简单地比较行并将总匹配数除以总行数,但我不认为这会非常有效.

piR*_*red 7

设置
创建2个时间序列

from StringIO import StringIO
import pandas as pd


txt1 = """2016-10-05 11:50:02.000734    0.50
2016-10-05 11:50:03.000033    0.25
2016-10-05 11:50:10.000479    0.50
2016-10-05 11:50:15.000234    0.25
2016-10-05 11:50:37.000199    0.50
2016-10-05 11:50:49.000401    0.50
2016-10-05 11:50:51.000362    0.25
2016-10-05 11:50:53.000424    0.75
2016-10-05 11:50:53.000982    0.25
2016-10-05 11:50:58.000606    0.75"""

s1 = pd.read_csv(StringIO(txt1), sep='\s{2,}', engine='python',
                 parse_dates=[0], index_col=0, header=None,
                 squeeze=True).rename('s1').rename_axis(None)

txt2 = """2016-10-05 11:50:07.000537    0.50
2016-10-05 11:50:11.000994    0.50
2016-10-05 11:50:19.000181    0.50
2016-10-05 11:50:35.000578    0.50
2016-10-05 11:50:46.000761    0.50
2016-10-05 11:50:49.000295    0.75
2016-10-05 11:50:51.000835    0.75
2016-10-05 11:50:55.000792    0.25
2016-10-05 11:50:55.000904    0.75
2016-10-05 11:50:57.000444    0.75"""

s2 = pd.read_csv(StringIO(txt2), sep='\s{2,}', engine='python',
                 parse_dates=[0], index_col=0, header=None,
                 squeeze=True).rename('s2').rename_axis(None)
Run Code Online (Sandbox Code Playgroud)

TL; DR

df = pd.concat([s1, s2], axis=1).ffill().dropna()
overlap = df.index.to_series().diff().shift(-1) \
            .fillna(0).groupby(df.s1.eq(df.s2)).sum()
overlap.div(overlap.sum())

False    0.666657
True     0.333343
Name: duration, dtype: float64
Run Code Online (Sandbox Code Playgroud)

说明

建立基地 pd.DataFrame df

  • 用于pd.concat对齐索引
  • 用于ffill让值向前传播
  • 用于dropna在另一个系列开始之前摆脱一个系列的值

df = pd.concat([s1, s2], axis=1).ffill().dropna()
df
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

'duration'
从当前时间戳计算到下一个

df['duration'] = df.index.to_series().diff().shift(-1).fillna(0)
df
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

计算重叠

  • df.s1.eq(df.s2)给出s1重叠时的布尔序列s2
  • 使用groupby上面的布尔系列来聚合总和持续时间True和False

overlap = df.groupby(df.s1.eq(df.s2)).duration.sum()
overlap

False   00:00:33.999548
True    00:00:17.000521
Name: duration, dtype: timedelta64[ns]
Run Code Online (Sandbox Code Playgroud)

具有相同值的时间百分比

overlap.div(overlap.sum())

False    0.666657
True     0.333343
Name: duration, dtype: float64
Run Code Online (Sandbox Code Playgroud)