Python按条件替换DataFrame列值时误删非目标行数据的解决方法
按条件覆盖DataFrame列值的实现方法
问题描述
需要对数据集按指定条件映射取值,覆盖对应行指定列的原有值,非匹配行保留原始数据。
原始数据
ID Date Location Used Status AA Q121 NY 20 ok AA Q221 NY 50 ok AA Q321 NY 10 ok BB Q121 CA 1 ok BB Q221 CA 0 yes BB Q321 CA 500 yes BB Q421 CA 700 no CC Q121 AZ 50 no
目标输出
ID Date Location Used Status AA Q121 NY closed AA Q221 NY closed AA Q321 NY closed BB Q121 CA 1 ok BB Q221 CA 0 yes BB Q321 CA 500 yes BB Q421 CA 700 no CC Q121 AZ 50 no
现有错误代码
df['Used'] = np.where(((df.ID == 'AA') & (df.Date >= 'Q121')), '', df['Used']) df['Status'] = np.where(((df.ID == 'AA') & (df.Date >= 'Q121')), 'closed', '')
该代码的问题是:匹配条件的行Status可以正确替换为closed,但所有不满足条件的行对应列值会被错误替换为空值。
错误原因
np.where(condition, x, y)的逻辑是:满足条件返回x,不满足条件返回y。原来写Status列的替换逻辑时,不满足条件的返回值写的是空字符串'',相当于直接把非目标行的原有值覆盖成空,自然会丢失数据。
修正方法
方法1:修正np.where参数
把不满足条件时的返回值从空字符串改成对应列的原始值即可,建议先把筛选条件存为变量避免重复书写:
import numpy as np # 定义需要匹配的行筛选条件 filter_mask = (df['ID'] == 'AA') & (df['Date'] >= 'Q121') df['Used'] = np.where(filter_mask, '', df['Used']) df['Status'] = np.where(filter_mask, 'closed', df['Status'])
方法2:用pandas原生loc索引赋值(更推荐,逻辑更直观)
直接通过布尔索引选中需要修改的行和列赋值,未被选中的行不会做任何改动,完全保留原始值:
filter_mask = (df['ID'] == 'AA') & (df['Date'] >= 'Q121') df.loc[filter_mask, 'Used'] = '' df.loc[filter_mask, 'Status'] = 'closed'
两种写法执行后都能得到目标结果,不会误改非匹配行的原有数据。
内容的提问来源于stack exchange,提问作者Lynn
相关产品推荐
相关产品推荐

