如何高效地将两个时间序列交替组合?

3

假设我有两个非常长的系列 - 大和小

index = pd.date_range(start='1952', periods=10**6, freq='s')
big = pd.Series(np.ones(len(index))*97, index)
small = pd.Series(np.ones(len(index))*2, index)

我希望能创建一个新的系列,将bigsmall结合起来,交替使用它们的值,并使用borders来确定何时切换到另一个(例如,每5秒钟就有一个边框)。请保留HTML标签。
borders = pd.date_range(start='1952', periods=len(index)/5.0, freq='5s')

有没有一种高效的基于矩阵的操作组合可以用来实现这个?我尝试查看文档中的各种连接、合并等运算符,但没有找到任何提供类似逻辑的东西。
我可以使用for循环来实现这个,但即使对于一系列len()为10ˆ5的数据,也需要超过一分钟的时间。
alternating = pd.Series()
for i in range(1, 100, 2):
    b0 = borders[i-1]
    b1 = borders[i]
    b2 = borders[i+1]
    sec = pd.offsets.Second(1)
    alternating = alternating.append(small[b0:b1-sec]).append(big[b1:b2-sec])

alternating.head(24)的示例输出

1952-01-16 00:00:00     2
1952-01-16 00:00:01     2
1952-01-16 00:00:02     2
1952-01-16 00:00:03     2
1952-01-16 00:00:04     2
1952-01-16 00:00:05    97
1952-01-16 00:00:06    97
1952-01-16 00:00:07    97
1952-01-16 00:00:08    97
1952-01-16 00:00:09    97
1952-01-16 00:00:10     2
1952-01-16 00:00:11     2
1952-01-16 00:00:12     2
1952-01-16 00:00:13     2
1952-01-16 00:00:14     2
1952-01-16 00:00:15    97
1952-01-16 00:00:16    97
1952-01-16 00:00:17    97
1952-01-16 00:00:18    97
1952-01-16 00:00:19    97
1952-01-16 00:00:20     2
1952-01-16 00:00:21     2
1952-01-16 00:00:22     2
1952-01-16 00:00:23     2
1个回答

2
如果您的周期是不足一分钟的小数,可以尝试类似以下的方法:
index = pd.date_range(start='1952', periods=10**6, freq='s')
big = pd.Series(np.ones(len(index))*97, index)
small = pd.Series(np.ones(len(index))*2, index)

alternating = big[big.index.second % 10 >= 5].combine_first(small)

alternating 的外观与您要求的完全相同,并在150毫秒内计算。


太好了,这正是我需要的!奇怪的是,我知道这些方法各自是什么,但要在脑海中开始组合它们并不那么容易——我想到的第一件事总是一个基于结构和循环的算法……而要改变时间间隔,只需使条件更加复杂——例如,对于17秒,可以使用big.index.second / 17 % 2 == 0 - metakermit
顺便提一句,我注意到您的回复速度非常快。您是在使用什么应用程序吗?我尝试通过Stack Exchange订阅了一些标签,但我只收到每日的电子邮件摘要。有更快的方法吗? - metakermit
17秒不是一分钟的一部分,因此这个计算方法不能按预期工作(0..16、17..33、34..50、51..59,最后一个区间较短)。但您可以使用它来计算到某个固定日期时间的时间差总秒数或使用行号。 - eumiro
是的,很好发现。到目前为止我得到的是start = big.index[0].to_pydatetime()alternating = big[(big.index.to_pydatetime() - start).total_seconds() / 17 % 2 == 0],但我似乎找不到一种将total_seconds()调用映射到所有元素的方法。 - metakermit
@kermit666,这个怎么样:big[(big.index.astype(np.int64) / 10**9) % 34 >= 17].combine_first(small) - eumiro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接