如何基于Pandas DataFrame其他列的值更新对应单元格值
Pandas按labels列列表批量赋值对应列值为1的实现方案
问题背景
现有名为removedCols的Pandas DataFrame,共约2000行,初始状态下A、B、C、D四列值均为0,labels列存储每一行需要标记为1的列名列表,原始数据片段如下:
A B C D labels 0 0 0 0 ['D', 'C'] 0 0 0 0 [] 0 0 0 0 ['A','B','D'] 0 0 0 0 ['D']
需要实现的效果是:根据labels列存储的列名列表,将对应行对应列的单元格值替换为1,最终得到如下结果:
A B C D labels 0 0 1 1 ['D', 'C'] 0 0 0 0 [] 1 1 0 1 ['A','B','D'] 0 0 0 1 ['D']
原有代码错误原因
之前编写的遍历代码运行后0/1值随机错乱,核心原因是索引调用方式错误:
- 代码中
i是DataFrame的索引标签值,但removedCols.iloc[i]是按行的物理位置序号取数,不是按索引标签取数 - 只要DataFrame之前做过排序、筛选、拼接等操作导致索引不是从0开始的连续整数,就会取到错误行的
labels内容,最终赋值位置和实际标签不匹配 - 另外之前错误运行留下的脏数据没有清理,也会导致结果不符合预期
可用实现方案
方案1:修正后的遍历写法(逻辑直观易理解)
先重置目标列的值为0清除脏数据,再直接迭代labels列的索引和值,避免取错行:
# 先把目标列重置为0,清除之前错误赋值的残留数据 target_cols = ['A', 'B', 'C', 'D'] removedCols[target_cols] = 0 # 直接遍历labels列的索引和对应值,避免iloc的索引错位问题 for row_idx, col_list in removedCols['labels'].items(): for col_name in col_list: removedCols.at[row_idx, col_name] = 1
方案2:向量化实现(运行效率更高,适合2000行及以上规模数据)
不用写循环,用pandas自带方法直接生成二值矩阵赋值,速度更快:
import pandas as pd target_cols = ['A', 'B', 'C', 'D'] # 先重置目标列为0 removedCols[target_cols] = 0 # 把labels列展开后生成独热编码,按行聚合得到0/1矩阵 label_matrix = pd.get_dummies(removedCols['labels'].explode()).groupby(level=0).sum() # 对齐列顺序后赋值回原表,缺值补0 removedCols[target_cols] = label_matrix.reindex(columns=target_cols, fill_value=0)
如果环境已经安装scikit-learn,也可以用MultiLabelBinarizer实现,代码更简洁:
from sklearn.preprocessing import MultiLabelBinarizer target_cols = ['A', 'B', 'C', 'D'] mlb = MultiLabelBinarizer(classes=target_cols) removedCols[target_cols] = mlb.fit_transform(removedCols['labels'])
提示:如果后续
labels里可能出现A/B/C/D之外的列名,可以在赋值前加一层判断过滤,避免新增多余列。
内容的提问来源于stack exchange,提问作者Zeshan Fayyaz
相关产品推荐
相关产品推荐

