You can join MultiIndex Series created by DataFrame.stack:
l = [d.set_index(['a','b']).stack() for d in [df1,df2,df3]] df = pd.concat(l).unstack().sort_index(level=[1,0], ascending=[False, True]) print (df) c1 c2 a b id1 W 1.0 4.0 id2 W 2.0 5.0 id3 W 3.0 6.0 id1 Q 7.0 NaN id4 Q 8.0 NaN id5 Q 9.0 NaN
If there is only 3 columns DataFrames use DataFrame.squeeze or select first column by iloc[:, 0] for list of Series:
l = [d.set_index(['a','b']).squeeze() for d in [df1,df2,df3]] keys = [x.name for x in l] df = (pd.concat(l, axis=0, keys=keys) .unstack(0) .sort_index(level=[1,0], ascending=[False, True])) print (df) c1 c2 a b id1 W 1.0 4.0 id2 W 2.0 5.0 id3 W 3.0 6.0 id1 Q 7.0 NaN id4 Q 8.0 NaN id5 Q 9.0 NaN
l = [d.set_index(['a','b']).iloc[:, 0] for d in [df1,df2,df3]] keys = [x.name for x in l] df = (pd.concat(l, axis=0, keys=keys) .unstack(0) .sort_index(level=[1,0], ascending=[False, True]))
Another idea is chain multiple DataFrames in list by DataFrame.combine_first:
from functools import reduce dfs = [d.set_index(['a','b']) for d in [df1,df2,df3]] df = (reduce(lambda x, y: x.combine_first(y), dfs) .sort_index(level=[1,0], ascending=[False, True])) print (df) c1 c2 a b id1 W 1.0 4.0 id2 W 2.0 5.0 id3 W 3.0 6.0 id1 Q 7.0 NaN id4 Q 8.0 NaN id5 Q 9.0 NaN