在三个DataFrame中查找复合键的存在,并相应地连接DataFrame

时间:2018-06-15 07:30:58

标签: python pandas dataframe join merge

这个问题很难说出来。

以下是可重现示例的示例代码:

import numpy as np
import pandas as pd    

df1 = pd.DataFrame([['a', 1, 10, 1], ['a', 2, 20, 1], ['b', 1, 4, 1], ['c', 1, 2, 1], ['e', 2, 10, 1]])
df2 = pd.DataFrame([['a', 1, 15, 2], ['a', 2, 20, 2], ['c', 1, 2, 2]])
df3 = pd.DataFrame([['d', 1, 10, 3], ['e', 2, 20, 3], ['f', 1, 15, 3]])    

df1.columns = ['name', 'id', 'price', 'part']
df2.columns = ['name', 'id', 'price', 'part']
df3.columns = ['name', 'id', 'price', 'part']    



result = pd.DataFrame([['a', 1, 10, 15, 'missing'],
['a', 2, 20, 20, 'missing'],
['b', 1, 4, 'missing', 'missing'],
['c', 1, 2, 2, 'missing'],
['e', 2, 10, 'missing', 20],
['d', 1, 'missing', 'missing', 10],
['f', 1, 'missing', 'missing', 15]])    

result.columns = ['name', 'id', 'pricepart1', 'pricepart2', 'pricepart3']

所以有三个DataFrame:

df1

  name  id  price  part
0    a   1     10     1
1    a   2     20     1
2    b   1      4     1
3    c   1      2     1
4    e   2     10     1

df2

  name  id  price  part
0    a   1     15     2
1    a   2     20     2
2    c   1      2     2

df3

    name  id  price  part
0    d   1     10     3
1    e   2     20     3
2    f   1     15     3

nameid就像一个复合键。它可能存在于所有三个DataFrame中,只有三个DataFrame中的两个,仅存在于一个DataFrame中。为了表示name, id来自哪个DataFrame,partdf1df2中存在df3列。

我正在寻找的结果由result DataFrame提供。

  name  id pricepart1 pricepart2 pricepart3
0    a   1         10         15    missing
1    a   2         20         20    missing
2    b   1          4    missing    missing
3    c   1          2          2    missing
4    e   2         10    missing         20
5    d   1    missing    missing         10
6    f   1    missing    missing         15

基本上,我想要考虑每个nameid对。即使同一个nameid同时包含df1df2,我也希望每个price的{​​{1}}都有单独的列如果两个部分/ DataFrame中的价格相同。

part DataFrame中,选择row1,results

这代表的是,a 1 10 15 missingname, id的价格为a 1 10df1 15,{在df2中{1}}。

如果特定missing的行值为df3,则missing对未出现在该特定的DataFrame中!

我已使用pricepart来表示DataFrame!因此,您可以name, id始终part始终part,始终1 df1 2 df2 3 df3

到目前为止......我确实做到了,pd.concat([df1, df2, df3])

不确定这种方法是否会导致死胡同......

请注意,原始的三个DataFrame是62245 rows × 4 columns EACH。每个DataFrame可能包含也可能不包含nameid对。如果nameid对存在于数据框架的偶数1中,而不存在于其他数据框架中,我希望对其他数据框架使用missing进行说明。

1 个答案:

答案 0 :(得分:2)

您可以在使用pd.merge

时使用how='outer'
# Change column names and remove 'part' column
df1 = df1.rename(columns={'price':'pricepart1'}).drop('part', axis=1)
df2 = df2.rename(columns={'price':'pricepart2'}).drop('part', axis=1)
df3 = df3.rename(columns={'price':'pricepart3'}).drop('part', axis=1)

# Merge dataframes
df = pd.merge(df1, df2, left_on=['name', 'id'], right_on=['name', 'id'], how='outer')
df = pd.merge(df , df3, left_on=['name', 'id'], right_on=['name', 'id'], how='outer')

# Fill na values with 'missing'
df = df.fillna('missing')

Out[]: 
  name  id pricepart1 pricepart2 pricepart3
0    a   1         10         15    missing
1    a   2         20         20    missing
2    b   1          4    missing    missing
3    c   1          2          2    missing
4    e   2         10    missing         20
5    d   1    missing    missing         10
6    f   1    missing    missing         15