Python Pandas:如何将独热编码逆向转换为分类变量
解决方案
这里有几种简洁高效的方法来实现你想要的效果,都是基于Pandas原生操作,不用写复杂的循环:
方法1:使用idxmax()(最简洁)
因为你的每行恰好只有一个1,所以可以直接用idxmax()沿着行的方向(axis=1)获取值最大的列名,也就是值为1的那个列:
import pandas as pd # 构造你的DataFrame df = pd.DataFrame({ 'id': [1,1,2,2,3,3], 'ind_1': [0,1,0,0,0,1], 'ind_2': [1,0,1,0,0,0], 'ind_3': [0,0,0,1,1,0] }) # 添加ind_all列 df['ind_all'] = df[['ind_1', 'ind_2', 'ind_3']].idxmax(axis=1)
这样就能直接得到你要的结果啦,idxmax()会返回每行中第一个最大值的列名,刚好完美匹配你的场景。
方法2:使用矩阵点积(dot())
如果以后你的行可能出现多个1(需要用逗号分隔列名),这个方法会更通用:
# 获取指标列的列表 cols = ['ind_1', 'ind_2', 'ind_3'] # 用dot乘积把列名和对应的值相乘,最后拼接结果 df['ind_all'] = df[cols].dot(cols + ', ').str.rstrip(', ')
原理很简单:每行中值为1的列会保留列名,值为0的会被忽略,最后去掉末尾多余的逗号和空格。就算你现在的场景只有一个1,这个方法也能得到和上面完全一致的结果。
方法3:使用apply()(直观但效率稍低)
如果你喜欢更直白的写法,可以用apply()逐行处理:
def get_ind_name(row): # 遍历列名,找到值为1的那个 for col in ['ind_1', 'ind_2', 'ind_3']: if row[col] == 1: return col return '' # 处理没有1的边界情况 df['ind_all'] = df.apply(get_ind_name, axis=1)
不过要注意,apply()本质是逐行循环,当DataFrame数据量很大时,效率会比前两种向量式操作低一些,所以更推荐前两种方法。
最终验证结果
运行上面任意一种方法后,你都会得到期望的输出:
id ind_1 ind_2 ind_3 ind_all 0 1 0 1 0 ind_2 1 1 1 0 0 ind_1 2 2 0 1 0 ind_2 3 2 0 0 1 ind_3 4 3 0 0 1 ind_3 5 3 1 0 0 ind_1
内容的提问来源于stack exchange,提问作者Pylander
相关产品推荐
相关产品推荐

