[英]Full outer join of two or more data frames
給定以下三個Pandas數據幀,我需要將它們合並為類似於SQL全外連接。 注意,密鑰是多索引type_N
和id_N
, N
= 1,2,3:
import pandas as pd
raw_data = {
'type_1': [0, 1, 1,1],
'id_1': ['3', '4', '5','5'],
'name_1': ['Alex', 'Amy', 'Allen', 'Jane']}
df_a = pd.DataFrame(raw_data, columns = ['type_1', 'id_1', 'name_1' ])
raw_datab = {
'type_2': [1, 1, 1, 0],
'id_2': ['4', '5', '5', '7'],
'name_2': ['Bill', 'Brian', 'Joe', 'Bryce']}
df_b = pd.DataFrame(raw_datab, columns = ['type_2', 'id_2', 'name_2'])
raw_datac = {
'type_3': [1, 0],
'id_3': ['4', '7'],
'name_3': ['School', 'White']}
df_c = pd.DataFrame(raw_datac, columns = ['type_3', 'id_3', 'name_3'])
預期結果應該是:
type_1 id_1 name_1 type_2 id_2 name_2 type_3 id_3 name_3
0 3 Alex NaN NaN NaN NaN NaN NaN
1 4 Amy 1 4 Bill 1 4 School
1 5 Allen 1 5 Brian NaN NaN NaN
1 5 Allen 1 5 Joe NaN NaN NaN
1 5 Jane 1 5 Brian NaN NaN NaN
1 5 Jane 1 5 Joe NaN NaN NaN
NaN NaN NaN 0 7 Bryce 0 7 White
如何在熊貓中實現這一目標?
我建議你讓生活變得不那么復雜,並且你想要合並的東西沒有不同的名字。
da = df_a.set_index(['type_1', 'id_1']).rename_axis(['type', 'id'])
db = df_b.set_index(['type_2', 'id_2']).rename_axis(['type', 'id'])
dc = df_c.set_index(['type_3', 'id_3']).rename_axis(['type', 'id'])
da.join(db, how='outer').join(dc, how='outer')
name_1 name_2 name_3
type id
0 3 Alex NaN NaN
7 NaN Bryce White
1 4 Amy Bill School
5 Allen Brian NaN
5 Allen Joe NaN
5 Jane Brian NaN
5 Jane Joe NaN
這是獲取其他專欄的令人討厭的方法
from cytoolz.dicttoolz import merge
i = pd.DataFrame(d.index.values.tolist(), d.index, d.index.names)
d = d.assign(**merge(
i.mask(d[f'name_{j}'].isna()).add_suffix(f'_{j}').to_dict('l')
for j in [1, 2, 3]
))
d[sorted(d.columns, key=lambda x: x.split('_')[::-1])]
id_1 name_1 type_1 id_2 name_2 type_2 id_3 name_3 type_3
type id
0 3 3 Alex 0.0 NaN NaN NaN NaN NaN NaN
7 NaN NaN NaN 7 Bryce 0.0 7 White 0.0
1 4 4 Amy 1.0 4 Bill 1.0 4 School 1.0
5 5 Allen 1.0 5 Brian 1.0 NaN NaN NaN
5 5 Allen 1.0 5 Joe 1.0 NaN NaN NaN
5 5 Jane 1.0 5 Brian 1.0 NaN NaN NaN
5 5 Jane 1.0 5 Joe 1.0 NaN NaN NaN
您可以使用2個連續合並,首先在df_a
和df_b
,然后在df_c
:
In [49]: df_temp = df_a.merge(df_b, how='outer', left_on=['type_1', 'id_1'], right_on=['type_2', 'id_2'])
In [50]: df_temp.merge(df_c, how='outer', left_on=['type_2', 'id_2'], right_on=['type_3', 'id_3'])
Out[50]:
type_1 id_1 name_1 type_2 id_2 name_2 type_3 id_3 name_3
0 0.0 3 Alex NaN NaN NaN NaN NaN NaN
1 1.0 4 Amy 1 4 Bill 1.0 4 School
2 1.0 5 Allen 1 5 Brian NaN NaN NaN
3 1.0 5 Allen 1 5 Joe NaN NaN NaN
4 1.0 5 Jane 1 5 Brian NaN NaN NaN
5 1.0 5 Jane 1 5 Joe NaN NaN NaN
6 NaN NaN NaN 0 7 Bryce 0.0 7 White
讓我們嘗試為此創建一個新密鑰,我在這里使用reduce
import functools
dfs=[df_a,df_b,df_c]
dfs=[x.assign(key=list(zip(x.iloc[:,0],x.iloc[:,1]))) for x in dfs]
merged_df = functools.reduce(lambda left,right: pd.merge(left,right,on='key',how='outer'), dfs)
merged_df.drop('key',1)
Out[110]:
type_1 id_1 name_1 type_2 id_2 name_2 type_3 id_3 name_3
0 0.0 3 Alex NaN NaN NaN NaN NaN NaN
1 1.0 4 Amy 1.0 4 Bill 1.0 4 School
2 1.0 5 Allen 1.0 5 Brian NaN NaN NaN
3 1.0 5 Allen 1.0 5 Joe NaN NaN NaN
4 1.0 5 Jane 1.0 5 Brian NaN NaN NaN
5 1.0 5 Jane 1.0 5 Joe NaN NaN NaN
6 NaN NaN NaN 0.0 7 Bryce 0.0 7 White
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.