我有兩個資料框:
df_A = pd.DataFrame({'start_date':['2021-04-01 00:00:00','2021-05-01 00:00:00', '2021-05-02 00:00:00'],'end_date':['2021-04-01 00:11:00','2021-05-01 00:06:00', '2021-05-03 00:00:00'], 'eventname':['birthday', 'wedding', 'birthday'] })
df_B = pd.DataFrame({'event_date':['2021-04-01 00:06:00','2021-05-01 00:03:00', '2021-05-04 00:00:00'],'price':[100,200,500]})
df_A['end_date'] = pd.to_datetime(df_A.end_date)
df_A['start_date'] = pd.to_datetime(df_A.start_date)
df_B['event_date'] = pd.to_datetime(df_B.event_date)
df_A
start_date end_date eventname
0 2021-04-01 2021-04-01 00:11:00 birthday
1 2021-05-01 2021-05-01 00:06:00 wedding
2 2021-05-02 2021-05-03 00:00:00 birthday
df_B
event_date price
0 2021-04-01 00:06:00 100
1 2021-05-01 00:03:00 200
2 2021-05-04 00:00:00 500
我想加入它們,使event_date列位于df_A的start_date和end_date列之間。這是我的代碼:
df_A.index = pd.IntervalIndex.from_arrays(df_A['start_date'],df_A['end_date'],closed='both')
df_B['start_date'] = df_B['event_date'].apply(lambda x : df_A.iloc[df_A.index.get_loc(x)]['start_date'])
df_B
但是,我收到一個關鍵錯誤,因為event_datedf_B 列上的某些值不在 df_A 中的任何start_date和end_date列之間。
這是我的預期輸出:
event_date price start_date
0 2021-04-01 00:06:00 100 2021-04-01
1 2021-05-01 00:03:00 200 2021-05-01
2 2021-05-04 00:00:00 500 NaN
我嘗試使用交集,但只有在值完全相等時才有效。我該怎么做呢?
uj5u.com熱心網友回復:
如果您的start_date和end_date不重疊,請創建一個間隔索引并合并您的兩個資料框:
bins = pd.IntervalIndex.from_arrays(df_A['start_date'],
df_A['end_date'],
closed='both')
out = df_B.assign(interval=pd.cut(df_B['event_date'], bins)) \
.merge(df_A.assign(interval=bins), on='interval', how='left')
print(out[['event_date', 'price', 'start_date']])
# Output:
event_date price start_date
0 2021-04-01 00:06:00 100 2021-04-01
1 2021-05-01 00:03:00 200 2021-05-01
2 2021-05-04 00:00:00 500 NaT
uj5u.com熱心網友回復:
如果您可以避免非對等連接,那么就這樣做;使用分桶技術,類似于@Corralien 的優秀答案,其中 bin 不重疊(更快/更有效)。如果可能的話,另一種選擇是找到一種方法來引入合并連接,也許聯合您的最終輸出 -> 步驟可能會更長,但是,我覺得如果做得對,它會比非對等連接更有效。但是,如果您只關心第一場比賽,那么pd.merge_asof應該就足夠了。
回到問題:
一種選擇是通過conditional_join從pyjanitor:
# pip install pyjanitor
import pandas as pd
import janitor
(df_A.conditional_join(
df_B,
# column from left frame, column from right frame, comparision operator
('start_date', 'event_date', '<='),
('end_date', 'event_date', '>='),
how = 'right')
.filter(['event_date', 'price', 'start_date'])
)
event_date price start_date
0 2021-04-01 00:06:00 100 2021-04-01
1 2021-05-01 00:03:00 200 2021-05-01
2 2021-05-04 00:00:00 500 NaT
它的作用是比較來自df_Awith 的列df_B:
('start_date', 'event_date', '<=')表示檢查start_datefromdf_A是否<= event_date來自df_B。相同的概念適用于其他條件。這里的引數是變數 args,意味著你可以傳遞盡可能多的條件。列必須是相同的型別(浮點與浮點,整數與整數,日期與日期,...)。
在幕后,它對非等連接使用二分搜索(主要是為了避免笛卡爾連接,隨著資料幀大小的增長,這可能會導致記憶體效率低下);對于這種情況下的范圍連接,它使用簡單的搜索來減少搜索空間以獲得匹配的行。
該函式可以處理重疊索引,以及范圍連接涉及兩個不同列的場景 -> a < b and c > d。
您可以在此處查看更多示例
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/390727.html
上一篇:過濾后如何保留該行?
