I across this problem when using python for a double-level header. and found the same problem from other forum as states below:
When concatenating DataFrames and the header is douple-level, the column names get alphanumerically sorted if there are any differences between them. If they're identical across DataFrames, they don't get sorted.
This sort is undocumented and unwanted. Certainly the default behavior should be no-sort. For example:
I have two dataframe
# df1: C A B # df2: C A B D
1 2 3 1 2 3 4
0 4 5 6 0 5 6 7 8
1 7 8 9 1 9 10 11 12
if I print "Cols sorted", concat([df1,df2], sort = False)
# Cols sorted A B C D
2 3 1 4
0 5 6 4 NaN
1 8 9 7 NaN
But I want to keep it as the original order like:
# Cols wanted: C A B D
1 2 3 4
0 4 5 6 NaN
1 7 8 9 NaN
since df1 is placed in the first place when I concatenate them. When I use df1.append(df2)
, I have the same problem.
Also I am organizing a DataFrame with 60+ columns. So I can just create a new list of column names in right order and just simply do df = df[list of column name in original order]
Interesting problem... However, I think I found a work around the sort=False failing on multiindex column dataframe concatenations.
Let's first concat the dataframe column indexes together by converting them a dataframe and using pd.concat. Then we use that index of that result to reindex the column axis of the pd.concat dataframes to get the original column order back.
Setup:
df = pd.DataFrame({'A':np.random.choice(list('ABC'),10) , 'B':np.random.randint(0,5,10),'C':np.random.random(10)})
df1 = df.set_index(['A','B'], append=True)['C'].unstack([1,2])
df = pd.DataFrame({'A':np.random.choice(list('DEF'),10) , 'B':np.random.randint(0,5,10),'C':np.random.random(10)})
df2 = df.set_index(['A','B'], append=True)['C'].unstack([1,2])
print(df1)
A B C B A C B
B 1 4 2 0 0 4 4 2
0 0.657680 NaN NaN NaN NaN NaN NaN NaN
1 0.518157 NaN NaN NaN NaN NaN NaN NaN
2 NaN 0.776922 NaN NaN NaN NaN NaN NaN
3 NaN NaN 0.063375 NaN NaN NaN NaN NaN
4 0.328447 NaN NaN NaN NaN NaN NaN NaN
5 NaN NaN NaN 0.598312 NaN NaN NaN NaN
6 NaN NaN NaN NaN 0.918801 NaN NaN NaN
7 NaN NaN NaN NaN NaN 0.045484 NaN NaN
8 NaN NaN NaN NaN NaN NaN 0.71723 NaN
9 NaN NaN NaN NaN NaN NaN NaN 0.246769
print(df2)
A D E D F E
B 1 0 0 3 2 3 2 4
0 0.396883 NaN NaN NaN NaN NaN NaN NaN
1 NaN 0.789478 NaN NaN NaN NaN NaN NaN
2 NaN NaN 0.076724 NaN NaN NaN NaN NaN
3 NaN NaN NaN 0.424836 NaN NaN NaN NaN
4 NaN NaN NaN NaN 0.970031 NaN NaN NaN
5 NaN NaN NaN NaN NaN 0.119261 NaN NaN
6 0.781708 NaN NaN NaN NaN NaN NaN NaN
7 NaN NaN NaN NaN NaN NaN 0.57147 NaN
8 NaN NaN NaN NaN NaN NaN NaN 0.407157
9 NaN NaN NaN NaN 0.932431 NaN NaN NaN
First, let's try pd.concat([df1,df2], sort=False)
, print head(2):
A A B C D E F
B 0 4 0 1 2 4 2 4 0 1 2 3 0 4 2 3
0 NaN NaN NaN 0.657680 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 NaN NaN NaN 0.518157 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
Nope, that didn't work.
So, lets concat column indexes from both dataframes first.
orig_cols = pd.concat([df1.columns.to_frame(), df2.columns.to_frame()]).index
pd.concat([df1,df2]).reindex(orig_cols, axis=1)
Now let's look at output of head(2):
A B C B A C B D E D F E
B 1 4 2 0 0 4 4 2 1 0 0 3 2 3 2 4
0 0.657680 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 0.518157 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
It worked.