2017-06-22 50 views
1

合併:熊貓通過重疊範圍在給定以下兩個DataFrames

import pandas as pd 
a=pd.DataFrame({' ID':[1,1,2,2],'a.A':[1,5,10,15],'a.B':[3,8,13,18]}) 
b=pd.DataFrame({' ID':[1,1,2,2],'b.A':[2,2,14,18],'b.B':[3,2,15,20]}) 
a 
    ID a.A  a.B 
0 1  1  3 
1 1  5  8 
2 2  10 13 
3 2  15 18 

b 
    ID b.A  b.B 
0 1  2  3 
1 1  2  2 
2 2  14 15 
3 2  18 20 

我需要左加入B到A,其中A.A的到A·B的範圍內與該b.A到b.B的重疊對於給定的ID號。邏輯也可以這樣解釋: 如果ID與a和b匹配,則如果(a.A < = b.A和a.B> = b.A)或(a.A < = b.B且a.B> = b.B)則匹配。

最後的結果是這樣的:

ID a.A  a.B b.A b.B 
0 1  1  3  2  3 
1 1  1  3  2  2 
2 1  5  8   
3 2  10  13   
4 2  15  18 18  20 
5 2  15  18 18  20 

提前感謝!

+0

這是你想要的正確輸出嗎?我不確定第4行。請參閱我的答案。 –

回答

1
import pandas as pd 
import numpy as np 
a=pd.DataFrame({' ID':[1,1,2,2],'a.A':[1,5,10,15],'a.B':[3,8,13,18]}) 
b=pd.DataFrame({' ID':[1,1,2,2],'b.A':[2,2,14,18],'b.B':[3,2,15,20]}) 

c = a.merge(b, on=' ID', how='left') 
range_overlaps = (
    ((c['a.A'] <= c['b.A']) & (c['a.B'] >= c['b.A'])) | 
    ((c['a.A'] <= c['b.B']) & (c['a.B'] >= c['b.B'])) 
) 
c.loc[~range_overlaps, ['b.A', 'b.B']] = np.nan 
c = c.drop_duplicates() 
c = c.reset_index(drop=True) 

print(c) 

給出:

ID a.A a.B b.A b.B 
0 1 1 3 2.0 3.0 
1 1 1 3 2.0 2.0 
2 1 5 8 NaN NaN 
3 2 10 13 NaN NaN 
4 2 15 18 14.0 15.0 
5 2 15 18 18.0 20.0 
+0

這兩個優秀的迴應。如果我在兩列中有多個匹配的相同數字,我可能會丟棄b.A,而不是使用drop重複。非常感謝你們兩位! –

2

不知道這是最好的解決辦法,但它可以是一個良好的開端:

import pandas as pd 
a=pd.DataFrame({' ID':[1,1,2,2],'a.A':[1,5,10,15],'a.B':[3,8,13,18]}) 
b=pd.DataFrame({' ID':[1,1,2,2],'b.A':[2,2,14,18],'b.B':[3,2,15,20]}) 

c = a.merge(b) 
cbAB = (c["a.A"] <= c["b.A"]) & (c["a.B"] >= c["b.A"]) | (c["a.A"] <= c["b.B"]) & (c["a.B"] >= c["b.B"]) 
cb = c[["b.A","b.B"]] 
cb = cb[cbAB] 
c[["b.A","b.B"]] = cb 

c = c.drop_duplicates() 

c輸出是:

>>> c 
    ID a.A a.B b.A b.B 
0 1 1 3 2 3 
1 1 1 3 2 2 
2 1 5 8 NaN NaN 
4 2 10 13 NaN NaN 
6 2 15 18 14 15 
7 2 15 18 18 20