熊猫根据其他列向列多索引添加新的第二级列

Zha*_*g18 5 multi-index dataframe pandas

我有一个带有列多索引的DataFrame:

System   A                B
Trial    Exp1    Exp2     Exp1    Exp2
1        NaN     1        2       3
2        4       5        NaN     NaN
3        6       NaN      7       8
Run Code Online (Sandbox Code Playgroud)

对于每个系统(A, B)和每个度量(1, 2, 3以索引表示),结果Exp1始终优于Exp2。因此,我想为每个系统生成一个第三列,将其命名为Final,该列应Exp1在可用时使用,Exp2否则默认使用。理想的结果是

System   A                       B
Trial    Exp1    Exp2    Final   Exp1    Exp2    Final
1        NaN     1       1       2       3       2
2        4       5       4       NaN     NaN     NaN
3        6       NaN     6       7       8       7
Run Code Online (Sandbox Code Playgroud)

做这个的最好方式是什么?

我试图groupby在列上使用:

grp = df.groupby(level=0, axis=1)
Run Code Online (Sandbox Code Playgroud)

并且正在考虑使用其中之一transformapply结合使用assign来实现它。但是无法找到可行的方法或有效的方法。具体来说,for出于效率方面的考虑,我避免使用本机python 循环(否则问题就不那么重要了)。

jez*_*ael 6

使用stack的重塑,增加其列fillna由然后重塑回unstackswaplevel+ sort_index

df = df.stack(level=0)
df['Final'] = df['Exp1'].fillna(df['Exp1'])
df = df.unstack().swaplevel(0,1,axis=1).sort_index(axis=1)
print (df)
System    A               B           
Trial  Exp1 Exp2 Final Exp1 Exp2 Final
1       NaN  1.0   NaN  2.0  3.0   2.0
2       4.0  5.0   4.0  NaN  NaN   NaN
3       6.0  NaN   6.0  7.0  8.0   7.0
Run Code Online (Sandbox Code Playgroud)

用另一种解决方案xs的选择DataFrames,创造新DataFramecombine_first,但缺少第二级-被添加MultiIndex.from_product和最后concat两个DataFrames在一起:

a = df.xs('Exp1', axis=1, level=1)
b = df.xs('Exp2', axis=1, level=1)
df1 =  a.combine_first(b)
df1.columns = pd.MultiIndex.from_product([df1.columns, ['Final']])
df = pd.concat([df, df1], axis=1).sort_index(axis=1)
print (df)
System    A               B           
Trial  Exp1 Exp2 Final Exp1 Exp2 Final
1       NaN  1.0   1.0  2.0  3.0   2.0
2       4.0  5.0   4.0  NaN  NaN   NaN
3       6.0  NaN   6.0  7.0  8.0   7.0
Run Code Online (Sandbox Code Playgroud)

类似的解决方案rename

a = df.xs('Exp1', axis=1, level=1, drop_level=False)
b = df.xs('Exp2', axis=1, level=1, drop_level=False)
df1 = a.rename(columns={'Exp1':'Final'}).combine_first(b.rename(columns={'Exp2':'Final'}))
df = pd.concat([df, df1], axis=1).sort_index(axis=1)
print (df)
System    A               B           
Trial  Exp1 Exp2 Final Exp1 Exp2 Final
1       NaN  1.0   1.0  2.0  3.0   2.0
2       4.0  5.0   4.0  NaN  NaN   NaN
3       6.0  NaN   6.0  7.0  8.0   7.0
Run Code Online (Sandbox Code Playgroud)