我有兩個 Pandas 事件資料框。第一個用于較長的事件,而第二個用于較短的事件。事件的開始和結束時間定義了它們。每個長事件都是至少一個短事件的“容器”。每個短事件僅是一個長事件間隔的一部分。
我試圖弄清楚每個長事件中有多少短事件/間隔。
最小的例子:
# long events
start | end | tag
0.5 | 0.7 | AAA
0.7 | 1.2 | BBB
1.2 | 2 | CCC
# short events
start | end | tag
0.5 | 0.55| a
0.55 | 0.7 | aa
0.7 | 1.2 | b
1.2 | 1.3 | c
1.3 | 1.4 | cc
1.4 | 1.5 | ccc
1.5 | 1.6 | cccc
1.6 | 2 | ccccc
所需的輸出是:
start | end | tag | count of sub events
0.5 | 0.7 | AAA | 2
0.7 | 1.2 | BBB | 1
1.2 | 2 | CCC | 5
我試圖使用“應用”,所以我創建了一個看起來像這樣的函式:
def count_records_in_time_range(df, start, end):
return len(df[(df['start'] >= start) & (df['end'] <= end)])
但我不知道如何繼續;我應該在短事件表還是長事件表上使用這個函式?如何根據另一個表(短事??件資料幀)中的記錄計算一個表(長事件資料幀)中每條記錄所需的計數?
uj5u.com熱心網友回復:
在開始和 fffill 上合并。groupby 并映射到 long 事件。
s=shortevents.merge(longevents.drop('end',1), how='left', on=['start'], suffixes=('','_y')).fillna(method='ffill')
longevents['count of sub events'] = longevents['tag'].map(s.groupby('tag_y').size())
start end tag count of sub events
0 0.5 0.7 AAA 2
1 0.7 1.2 BBB 1
2 1.2 2.0 CCC 5
uj5u.com熱心網友回復:
我們可以numpy broadcasting在這里使用
s, e = long[['start', 'end']].values[None, :].T
long['count'] = ((s <= short['start'].values) & (e >= short['end'].values)).sum(1)
start end tag count
0 0.5 0.7 AAA 2
1 0.7 1.2 BBB 1
2 1.2 2.0 CCC 5
uj5u.com熱心網友回復:
這是一個使用名為piso的包的解決方案,該包基于熊貓構建。
設定
long = pd.DataFrame(
{
"start":[0.5, 0.7, 1.2],
"end":[0.7, 1.2, 2],
"tag":["AAA", "BBB", "CCC"]
}
)
short = pd.DataFrame(
{
"start":[0.5, 0.55, 0.7, 1.2, 1.3, 1.4, 1.5, 1.6],
"end":[0.55, 0.7, 1.2, 1.3, 1.4, 1.5, 1.6, 2],
"tag":["a", "aa", "b", "c", "cc", "ccc", "cccc", "ccccc"],
}
)
解決方案
piso從較長的間隔匯入并創建間隔索引。我們將使用它作為系列的索引,其中的值來自tag列
import piso
long_ii = long.set_index(pd.IntervalIndex.from_arrays(long["start"], long["end"]))["tag"]
long_ii 看起來像這樣
(0.5, 0.7] AAA
(0.7, 1.2] BBB
(1.2, 2.0] CCC
Name: tag, dtype: object
如果每個短間隔都包含在一個長間隔內,那么檢查端點是否包含在間隔索引的間隔中就足夠了。由于間隔索引的默認值是右閉的,因此您需要檢查“結束”端點。如果我們在左閉合的情況下創建間隔索引,我們將檢查“開始”終點。
接下來,我們使用piso.lookupwhich 獲取一個資料幀或系列,由區間索引索引,并將其用作點陣列的查找表。例如
containers = piso.lookup(long_ii, short["end"])
containers 看起來像這樣
end
0.55 AAA
0.70 AAA
1.20 BBB
1.30 CCC
1.40 CCC
1.50 CCC
1.60 CCC
2.00 CCC
Name: tag, dtype: object
然后我們用 pandas.Series.value_counts
container_counts = containers.value_counts()
container_counts 看起來像這樣
CCC 5
AAA 2
BBB 1
Name: tag, dtype: int64
然后,您可以根據標簽將此系列加入原始資料幀以獲得所需的結果。
概括
import piso
long_ii = long.set_index(pd.IntervalIndex.from_arrays(long["start"], long["end"]))["tag"]
piso.lookup(long_ii, short["end"]).value_counts()
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/342480.html
