Pandas按sub_code列筛选后替换marks列值时保留非筛选行原数据
问题解决:筛选DataFrame并替换指定行的列值
原始DataFrame
import pandas as pd df = pd.DataFrame( {'stud_id' : [101, 101, 101, 101, 101, 101, 101, 101], 'sub_code' : ['CSE01', 'CSE02', 'CSE03', 'CSE06', 'CSE05', 'CSE04', 'CSE07', 'CSE08'], 'marks' : ['A','B','C','D', 'E','F','G','H']} )
需求
- a) 根据
sub_code列的指定值列表筛选DataFrame; - b) 将筛选出的行的
marks列值替换为常量FAIL,同时保留非筛选行的原marks值。
错误尝试及问题
尝试了以下代码,但运行后非筛选行的marks列变为NA:
sub_list = ['CSE01', 'CSE02', 'CSE03','CSE06', 'CSE05', 'CSE04'] df['marks'] = df[df['sub_code'].isin(sub_list)]['marks'].replace(r'^([A-Za-z])*$','FAIL', regex=True)
问题原因:直接将筛选后的替换结果赋值给整个marks列时,筛选范围外的行在原筛选结果中是缺失值(NaN),因此赋值后这些位置会被覆盖为NA。
正确解决方案
方法1:使用loc精准定位赋值(推荐)
通过布尔索引定位符合条件的行,直接修改对应列的值,其他行不受影响:
sub_list = ['CSE01', 'CSE02', 'CSE03','CSE06', 'CSE05', 'CSE04'] df.loc[df['sub_code'].isin(sub_list), 'marks'] = 'FAIL'
执行后得到的结果:
| stud_id | sub_code | marks |
|---|---|---|
| 101 | CSE01 | FAIL |
| 101 | CSE02 | FAIL |
| 101 | CSE03 | FAIL |
| 101 | CSE06 | FAIL |
| 101 | CSE05 | FAIL |
| 101 | CSE04 | FAIL |
| 101 | CSE07 | G |
| 101 | CSE08 | H |
方法2:使用mask函数替换
mask函数会将满足条件的位置替换为指定值,不满足条件的保留原值:
sub_list = ['CSE01', 'CSE02', 'CSE03','CSE06', 'CSE05', 'CSE04'] df['marks'] = df['marks'].mask(df['sub_code'].isin(sub_list), 'FAIL')
内容的提问来源于stack exchange,提问作者The Great
相关产品推荐
相关产品推荐

