如何在Pandas管道中展平多级索引列
我完全get你的需求了——你已经搞懂怎么把多级索引的列名合并成「数字_颜色」的格式,但不想直接硬改df.columns,而是想用链式调用(也就是管道风格)来实现,甚至想自己写个类似rename_columns的专属函数对吧?
先给你捋清楚之前踩的坑:你用df.rename(lambda x: ...)时触发了TypeError,是因为rename默认是用来修改行索引的!你的行索引是普通整数,所以lambda里的x是单个int值,自然没法用x[0]去取元素~ 要让rename处理列,得明确指定columns参数才行!
方法一:用原生rename直接实现链式调用
其实不用自己造轮子,只要给rename加上columns参数,就能完美实现你要的管道效果:
df.rename(columns=lambda col: f"{col[0]}_{col[1]}")
这里的lambda参数col就是每个多级列的元组(比如(1, 'red')),用f-string拼接比字符串相加更简洁直观,而且完全支持链式调用。
方法二:自定义rename_columns函数+pipe
如果你就是想自己实现一个rename_columns函数,用pipe来衔接是最顺的方式:
def rename_columns(df, rename_func): # 先复制原DataFrame,避免意外修改原数据 df_new = df.copy() # 用传入的函数处理每个列名 df_new.columns = [rename_func(col) for col in df_new.columns] return df_new # 链式调用示例 df.pipe(rename_columns, lambda col: f"{col[0]}_{col[1]}")
这个自定义函数接收两个参数:要处理的DataFrame,以及用来修改列名的函数。内部先复制DataFrame(防止原地修改),再重新设置列名,最后返回新的DataFrame,刚好能通过pipe实现链式调用。
方法三:一行式pipe写法(不用额外定义函数)
如果不想单独写函数,也可以直接在pipe里用匿名函数搞定:
df.pipe(lambda d: d.set_axis([f"{x[0]}_{x[1]}" for x in d.columns], axis=1))
这里用set_axis方法来批量设置列名,axis=1指定操作的是列轴,一行代码就能实现链式调用的展平效果。
测试验证
用你给出的测试数据跑一遍:
import pandas as pd arrays = [[1, 1, 2, 2], ["red", "blue", "red", "blue"]] ix = pd.MultiIndex.from_arrays(arrays, names=("number", "color")) df = pd.DataFrame([[10, 20, 30, 40], [50, 60, 70, 80]], columns=ix)
不管用上面哪种方法,都能得到你想要的展平列名结果,而且全程都是链式调用的管道风格~
备注:内容来源于stack exchange,提问作者robertspierre

