我有3个时间序列,需要随时间进行比较。显然,它们需要对齐以具有可比性。不幸的是,三分之二的时间序列是不规则的。另外2个范围是每天ID
每天进行2到50万次观测。
初始时间序列每300毫秒可用一次,可以与其他两个时间序列一起使用。
但是我有2个问题:
ID, time, value
的格式,即每个组分别构成一个单独的时间序列LEFT
和最精细的粒度在一段时间内可以联接,因为可能不存在精确匹配一些伪数据
import pandas as pd
from datetime import datetime
import numpy as np
def make_df(frequency, valueName):
date_rng = pd.date_range(start='2018-01-01', end='2018-01-02', freq=frequency)
ts = pd.Series(np.random.randn(len(date_rng)), index=date_rng)
groups = ['a', 'b', 'c', 'd', 'e']
group_series = [groups[np.random.randint(len(groups))] for i in range(0, len(date_rng))]
df = pd.DataFrame(ts, columns=[valueName])
df['group'] = group_series
return df
df_1 = make_df('ms', 'value_A')
display(df_1.head())
df_2 = make_df('H', 'value_B')
display(df_2.head())
df_3 = make_df('S', 'value_C')
display(df_3.head())
代码(不是真正的pythonic):
我尝试在SQL中尝试一些类似于a JOIN b ON a.group = b.group AND time in window(some_seconds)
的非等额联接,但是如果有多个记录匹配(即不仅第一条记录匹配,而且所有记录都匹配/生成了一行),这也会出现问题。
此外,我确实对类似于(spark):df.groupBy($"KEY", window($"time", "5 minutes")).sum("metric")
的数据进行分组,但这可能会造成很大的损失。
然后我发现(pandas)Pandas aligning multiple dataframes with TimeStamp index看起来已经很有趣了,但是只能产生完全匹配的内容。但是,当尝试使用df_2.join(df_3, how='outer', on=['group'], rsuffix='_1')
时,它不仅在(确切)时间加入,而且在group
时也失败,并显示错误消息,要求输入pd.concat
。
经过更多搜索后,我发现(pyspark)https://github.com/twosigma/flint在一定间隔内实现了时间序列联接-但是,我在使用它时遇到了问题。
答案 0 :(得分:1)
我找不到在熊猫中执行此操作的简单方法-因此我直接在spark中执行此操作。
火石是我的首选工具。最初,fl石在spark 2.2上不起作用,但在这里进行修复:https://github.com/geoHeil/flint/commit/a2827d38e155ec8ddd4252dc62d89181f14f0c47,以下代码就很好了:
val left = Seq((1,1L, 0.1), (1, 2L,0.2), (3,1L,0.3), (3, 2L,0.4)).toDF("groupA", "time", "valueA")
val right = Seq((1,1L, 11), (1, 2L,12), (3,1L,13), (3, 2L,14)).toDF("groupB", "time", "valueB")
val leftTs = TimeSeriesRDD.fromDF(dataFrame = left)(isSorted = false, timeUnit = MILLISECONDS)
val rightTS = TimeSeriesRDD.fromDF(dataFrame = right)(isSorted = false, timeUnit = MILLISECONDS)
val mergedPerGroup = leftTs.leftJoin(rightTS, tolerance = "1s")
即它对所有组执行某种笛卡尔连接:
mergedPerGroup.toDF.filter(col("groupA") === col("groupB")).show
+-------+------+------+------+------+
| time|groupA|valueA|groupB|valueB|
+-------+------+------+------+------+
|1000000| 3| 0.3| 3| 13|
|2000000| 3| 0.4| 3| 14|
使用删除不同的重复项。