[英]How to check if one Pandas time-series is present in another long time-series?
我有兩個很長的時間序列。 我必須檢查 A 系列中是否存在 B 系列(按給定順序)。
A系列:1、2、3、4、5、6、5、4、3。 B 系列:3、4、5。
結果:True,帶有找到小系列第一個元素的索引。 這里,索引:2(因為 3 出現在 A 系列的索引 2 處)
注:這兩個系列相當大。 假設 A 包含 50000 個元素,B 包含 350 個。
一個非常慢的解決方案是將系列轉換為列表並按順序檢查第一個列表是否是主列表的子集
def is_series_a_subseries_in_order(main, sub):
n = len(sub)
main=main.tolist()
sub=sub.tolist()
return any((main[i:i+n] == sub) for i in range(len(main)-n+1))
將返回True
或False
一種天真的方法是檢查 A 中的 B(1)。在你的例子中 B(1) = A(3),所以現在你必須檢查 B(2) = A(4) 並繼續直到結束你的子串...如果不正確,從 A(4) 開始,一直持續到最后。
搜索子串的更好方法是應用 Knuth-Morris-Pratt 算法。 我會讓你搜索更多關於它的信息!
不幸的是, pandas
的rolling
方法不允許用作迭代器,即使在#11704 中計划實現。
因此,我們必須自己實現一個滾動窗口來進行子集檢查。
ser_a = pd.Series(data=[1, 2, 3, 4, 5, 6, 5, 4, 3])
ser_b = pd.Series(data=[3, 4, 5])
slider_df = pd.concat(
[ser_a.shift(-i)[:ser_b.size] for i in range(ser_a.size - ser_b.size + 1)],
axis=1).astype(ser_a.dtype).T
sub_series = (ser_b == slider_df).all(axis=1)
# if you want, you can extract only the indices where a subseries was found:
sub_series_startindex = sub_series.index[sub_series]
我在這里做什么:
[ser_a.shift(-i)[:ser_b.size] for i in range(ser_a.size - ser_b.size + 1)]
:通過增加ser_a
移位創建一個“滾動窗口”,僅限於子的大小要檢查的系列ser_b
。 由於最后的移位將產生NaN
,因此這些被排除在range
。pd.concat(..., axis=1)
:連接移位系列,以便slider_df
包含列中的所有移位。.astype(ser_a.dtype)
:是嚴格可選的。 對於大型系列,這可能會提高性能,對於小型系列,它可能會降低性能。.T
:轉置 df,以便子系列索引按軸 0 對齊。sub_series = (ser_b == slider_df).all(axis=1)
:查找ser_b
匹配子系列的位置。sub_series.index[sub_series]
:提取找到匹配子系列的索引。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.