2017-08-01 25 views
1

ワイルドカード文字で複数の列を使用して2つのパンダデータフレームをマージしようとしています。ワイルドカードとのマージ

left=pd.DataFrame({'Type':['ABC','ADEC','OOO','DOG','MOT'], 'ID':[22,44,23,21,55]}) 
right=pd.DataFrame({'Type':['ABC','ADE*','*','DOG'], 'ID':[22,'*','23','2*'], 'Value': [0,1,1,0]}) 
result=pd.DataFrame({'Type':['ABC','ADEC','OOO','DOG','MOT'], 'ID':[22,44,23,21,55],'Value': [0,1,1,0,'NaN']}) 

与える:

left 
    ID Type 
0 22 ABC 
1 44 ADEC 
2 23 OOO 
3 21 DOG 
4 55 MOT 

right 
    ID Type Value 
0 22 ABC  0 
1 * ADE*  1 
2 23  *  1 
3 2* DOG  0 

result 
    ID Type Value 
0 22 ABC  0 
1 44 ADEC  1 
2 23 OOO  1 
3 21 DOG  0 
4 55 MOT NaN 

を私は使用してこれを実現しようとした:

は結果が必要なマージの結果であるデータセット、考えてみましょう

pd.merge(left=left, right=right, left_on=['Type', 'ID'], right_on ['Type','ID'], how='left') 

をしかし、結局:

pd.merge(left=left, right=right, left_on=['Type', 'ID'], right_on= ['Type','ID'], how='left') 
    ID Type Value 
0 22 ABC 0.0 
1 44 ADEC NaN 
2 23 OOO NaN 
3 21 DOG NaN 
4 55 MOT NaN 

ご協力いただきまして誠にありがとうございます。ありがとう!

+0

私はPandasがマージ、ジョインなどでワイルドカードを使用する機能を持っているとは思わない –

答えて

3
import pandas as pd 

left = pd.DataFrame(
    {'Type': ['ABC', 'ADEC', 'OOO', 'DOG', 'MOT'], 'ID': [22, 44, 23, 21, 55]}) 
right = pd.DataFrame({'Type': ['ABC', 'ADE*', '*', 'DOG'], 
         'ID': [22, '*', '23', '2*'], 'Value': [0, 1, 1, 0]}, 
        index=list('ABCD')) 
expected = pd.DataFrame({'Type': ['ABC', 'ADEC', 'OOO', 'DOG', 'MOT'], 'ID': [ 
         22, 44, 23, 21, 55], 'Value': [0, 1, 1, 0, 'NaN']}) 

data = {} 
for col in ['ID', 'Type']: 
    right[col] = right[col].astype(str).str.replace('*','.') 
    left[col] = left[col].astype(str) 
    data[col] = (right[col].apply(lambda pat: left.loc[left[col].str.match(pat), col]) 
       .stack().to_frame(col)) 
    data[col].index = data[col].index.droplevel(level=1) 

expanded = (data['ID'] 
      .join(data['Type']) 
      .join(right['Value'])) 

result = pd.merge(left, expanded, how='left') 


print(result) 

利回り

ID Type Value 
0 22 ABC 0.0 
1 44 ADEC 1.0 
2 23 OOO 1.0 
3 21 DOG 0.0 
4 55 MOT NaN 

あなたは.*を変更した場合は、正規表現のパターンとしてrightの値を考えることができます。 str.match(pat)を使用して、rightのパターンがleftに一致するかどうかをテストできます。例えば、

In [297]: right 
Out[297]: 
    ID Type Value 
A 22 ABC  0 
B . ADE.  1 
C 23  .  1 
D 2. DOG  0 

In [298]: left 
Out[298]: 
    ID Type 
0 22 ABC 
1 44 ADEC 
2 23 OOO 
3 21 DOG 
4 55 MOT 

In [271]: right['ID'].apply(lambda pat: left.loc[left['ID'].str.match(pat), 'ID']) 
Out[271]: 
    0 1 2 3 4 
A 22 NaN NaN NaN NaN 
B 22 44 23 21 55 
C NaN NaN 23 NaN NaN 
D 22 NaN 23 21 NaN 

このデータフレームはleft['ID']の値がパターンに一致するものrightの行ごとに示しています。たとえば、最後の行では、22,23および21left['ID']に一致するパターンが2.です。

我々stackこのDATAFRAME場合、我々はワイルドカード文字のすべての可能な拡張をリストアップシリーズを得る:

In [299]: right['ID'].apply(lambda pat: left.loc[left['ID'].str.match(pat), 'ID']).stack() 
Out[299]: 
A 0 22 
B 0 22 
    1 44 
    2 23 
    3 21 
    4 55 
C 2 23 
D 0 22 
    2 23 
    3 21 
dtype: object 

同じことがTypeのために行うことができます。

result = pd.merge(left, expanded, how='left') 

:今、所望の結果は leftexpandedの左マージすることによって得ることができる

In [301]: expanded = (data['ID'] 
         .join(data['Type']) 
         .join(right['Value'])) 
Out[301]: 
    ID Type Value 
A 22 ABC  0 
B 22 ADEC  1 
B 44 ADEC  1 
B 23 ADEC  1 
B 21 ADEC  1 
B 55 ADEC  1 
C 23 ABC  1 
C 23 ADEC  1 
C 23 OOO  1 
C 23 DOG  1 
C 23 MOT  1 
D 22 DOG  0 
D 23 DOG  0 
D 21 DOG  0 

:ワイルドカード文字のすべての有効な拡大を示していますDATAFRAMEを得るために、2つの結果を参加

PS:私はleftと上のインデックス値となるよう代わりに通常の [0,1,2,3]index=list('ABCD')を持っているrightを変更は発生しません 私たちは行を一致させる方法に揃えます。私は間違ってこの偶然を利用して解決策を開発するのを防ぐためにこれをしました。 。

関連する問題