如何对含索引的DataFrame执行melt操作,将True替换为对应列名?
实现DataFrame的melt转换并替换True值为列名的解决方案
首先先确认你的原始DataFrame:
import pandas as pd df = pd.DataFrame( [ ["True", "False"], ["True", "True"], ["False", "True"], ], index=["bob", "sue", "joe"], columns=["R1", "R2"], )
你需要把这个宽表转成指定的长表,保留原索引作为姓名列,同时只保留值为"True"的条目并把对应值替换成列名。下面是两种简洁的实现方式:
方法一:链式调用(推荐)
这种方式步骤清晰逻辑直观,一步就能搞定:
result_df = (df # 把原索引转为名为"Names"的列 .reset_index(names="Names") # 执行melt,将宽表转长表 .melt(id_vars="Names", var_name="Role", value_name="Value") # 筛选出值为"True"的行 .query('Value == "True"') # 删除不需要的Value列 .drop(columns="Value") # 重置结果索引(可选,让索引从0开始更整洁) .reset_index(drop=True) )
步骤拆解:
reset_index(names="Names"):把原来的行索引(bob、sue、joe)转换成单独的列,确保后续转换时不会丢失姓名信息。melt(...):将宽格式的DataFrame转为长格式,id_vars指定要保留的列(这里是Names),var_name设置原来的列名(R1/R2)要存放的新列名,value_name暂存原来的单元格值。query('Value == "True"'):只保留值为"True"的条目,过滤掉False的行。drop(columns="Value"):删除临时的Value列,只保留我们需要的Names和Role。reset_index(drop=True):重置结果的索引,让输出更规整。
运行后得到的结果完全符合你的要求:
Names Role 0 bob R1 1 sue R1 2 sue R2 3 joe R2
方法二:先替换值再转换
如果你习惯先把True值替换成对应列名再做转换,也可以这么写:
# 先将每个True值替换为所在列的列名,False保持不变 df_replaced = df.apply(lambda col: col.where(col == "False", col.name)) result_df = (df_replaced .reset_index(names="Names") .melt(id_vars="Names", var_name="Role", value_name="Value") # 过滤掉False的行 .query('Value != "False"') .drop(columns="Value") .reset_index(drop=True) )
这种方式和方法一结果完全一致,只是操作顺序不同,你可以根据自己的习惯选择。
内容的提问来源于stack exchange,提问作者pymat
相关产品推荐
相关产品推荐

