Pandas中实现两DataFrame列间双向子串匹配并更新字段
DataFrame多条件匹配设置字段值
原始数据
import pandas as pd # df_student_modules_nofail数据 data = { 'CCode': ['MG5002', 'MG5003', 'MG5005', 'MG5028', 'MG5029', 'MG5030', 'MG5033', 'MG6032', 'MG6037', 'MG6038', 'MG6103', 'MG6136', 'MG6051', 'MG7101', 'MG7121', 'DCFE700', 'MG6033', 'MG7026', 'MG7101B', 'MG7028'], 'PassFail': ['PASS'] * 20, 'CStat': ['Co', 'Co', 'Co', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'Co', 'C', 'E', 'A-MG7101A', 'Co', 'O', 'C', 'NM', 'Co', 'E'] } df_student_modules_nofail = pd.DataFrame(data) # dffc数据 data = { 'CCode': ['MG5004', 'MG7101A', 'MG5034'], 'PassFail': ['', '', ''], 'CStat': ['Co', 'Co', 'A-MG5033'] } dffc = pd.DataFrame(data)
需求
需满足以下任一条件时,将dffc的PassFail字段设为'Duplicate':
df_student_modules_nofail的CCode是dffc的CStat的子串;dffc的CCode是df_student_modules_nofail的CStat的子串。
第一个条件已实现,第二个条件实现时触发TypeError: unhashable type: 'Series'错误,最终期望输出:
data = { 'CCode': ['MG5004', 'MG7101A', 'MG5034'], 'PassFail': ['', 'Duplicate', 'Duplicate'], 'CStat': ['Co', 'Co', 'A-MG5033'] } dffc = pd.DataFrame(data)
错误原因
原代码中,mask = df_student_modules_nofail['CStat'].str.contains('|'.join(dffc['CCode']))生成的是长度为20的Series(对应df_student_modules_nofail的行数),而dffc只有3行,直接用dffc.loc[mask]会因索引不匹配报错。
解决方案
完整实现代码
# 条件1:df_student_modules_nofail的CCode是dffc的CStat的子串 mask1 = dffc['CStat'].str.contains('|'.join(df_student_modules_nofail['CCode'])) # 条件2:dffc的CCode是df_student_modules_nofail的CStat的子串 mask2 = dffc['CCode'].apply(lambda x: df_student_modules_nofail['CStat'].str.contains(x).any()) # 合并两个条件,满足任一即设置为Duplicate dffc.loc[mask1 | mask2, 'PassFail'] = 'Duplicate'
代码说明
- mask1:复用已实现的逻辑,检查
dffc的CStat是否包含df_student_modules_nofail中任意一个CCode; - mask2:遍历
dffc的每个CCode,检查df_student_modules_nofail的CStat中是否存在包含该CCode的记录,any()确保只要有一条满足就返回True; - 最终通过
mask1 | mask2合并两个条件,对满足任一条件的行设置PassFail为'Duplicate'。
运行上述代码后,dffc将完全符合期望输出。
内容的提问来源于stack exchange,提问作者ic198
相关产品推荐
相关产品推荐

