Merging Panda DataFrame on Index, with adding additional column, and not having duplicate index

Viewed 81
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
 'B': ['B0', 'B1', 'B2', 'B3'],
 'C': ['C0', 'C1', 'C2', 'C3'],
 'D': ['D0', 'D1', 'D2', 'D3']},
index=[0, 1, 2, 3])

df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
 'B': ['B4', 'B5', 'B6', 'B7'],
 'C': ['C4', 'C5', 'C6', 'C7'],
 'D': ['D4', 'D5', 'D6', 'D7']},
index=[4, 5, 6, 7])

df22 = pd.DataFrame({'A2': ['A4', 'A5', 'A6', 'A7'],
 'B2': ['B4', 'B5', 'B6', 'B7'],
 'C2': ['C4', 'C5', 'C6', 'C7'],
 'D2': ['D4', 'D5', 'D6', 'D7']},
index=[4, 5, 6, 7])

frames = [df1, df2, df22]
result = pd.concat(frames,sort=False)
result

enter image description here

As we see, index 4,5,6,7 are repeated, and NAN is added. How to merge meaningfully .. ?

NaN at A2 ,B2 ,C2, D2, at index 0,1,2,3 is acceptable

But Index 4,5,6,7 should not repeat and should not contain NaN

3 Answers

Do you want something like this? You can pd.concat vertically, the first two dataframes, the join that dataframe to df22 using the dataframe indexes.

 pd.concat([df1,df2]).join(df22)

Output:

    A   B   C   D   A2   B2   C2   D2
0  A0  B0  C0  D0  NaN  NaN  NaN  NaN
1  A1  B1  C1  D1  NaN  NaN  NaN  NaN
2  A2  B2  C2  D2  NaN  NaN  NaN  NaN
3  A3  B3  C3  D3  NaN  NaN  NaN  NaN
4  A4  B4  C4  D4   A4   B4   C4   D4
5  A5  B5  C5  D5   A5   B5   C5   D5
6  A6  B6  C6  D6   A6   B6   C6   D6
7  A7  B7  C7  D7   A7   B7   C7   D7

Another way is to use combine_first:

from functools import reduce
reduce(lambda x,y: x.combine_first(y), [df1,df2,df22])

or

df1.combine_first(df2).combine_first(df22)

Output:

    A   A2   B   B2   C   C2   D   D2
0  A0  NaN  B0  NaN  C0  NaN  D0  NaN
1  A1  NaN  B1  NaN  C1  NaN  D1  NaN
2  A2  NaN  B2  NaN  C2  NaN  D2  NaN
3  A3  NaN  B3  NaN  C3  NaN  D3  NaN
4  A4   A4  B4   B4  C4   C4  D4   D4
5  A5   A5  B5   B5  C5   C5  D5   D5
6  A6   A6  B6   B6  C6   C6  D6   D6
7  A7   A7  B7   B7  C7   C7  D7   D7

You can first concatenate df1 and df2, and then concatenate df22 with axis=1, like:

>>> pd.concat([pd.concat([df1, df2]), df22], axis=1)
    A   B   C   D   A2   B2   C2   D2
0  A0  B0  C0  D0  NaN  NaN  NaN  NaN
1  A1  B1  C1  D1  NaN  NaN  NaN  NaN
2  A2  B2  C2  D2  NaN  NaN  NaN  NaN
3  A3  B3  C3  D3  NaN  NaN  NaN  NaN
4  A4  B4  C4  D4   A4   B4   C4   D4
5  A5  B5  C5  D5   A5   B5   C5   D5
6  A6  B6  C6  D6   A6   B6   C6   D6
7  A7  B7  C7  D7   A7   B7   C7   D7

There are several options. For this exact scenario, I would suggest a merge followed by a join. I like this approach, because it feels more like database functions.

df1.merge(df2,how='outer').join(df22,how='outer')

A   B   C   D   A2  B2  C2  D2
0   A0  B0  C0  D0  NaN NaN NaN NaN
1   A1  B1  C1  D1  NaN NaN NaN NaN
2   A2  B2  C2  D2  NaN NaN NaN NaN
3   A3  B3  C3  D3  NaN NaN NaN NaN
4   A4  B4  C4  D4  A4  B4  C4  D4
5   A5  B5  C5  D5  A5  B5  C5  D5
6   A6  B6  C6  D6  A6  B6  C6  D6
7   A7  B7  C7  D7  A7  B7  C7  D7
Related