使用Pandas处理数据:将匹配值替换原列内容的方法
问题:替换CSV中匹配过滤条件的列值
输入CSV数据
| 姓名 | 角色 | 最后登录日期 |
|---|---|---|
| Phil | Role A | Role B | 2024/01/01 |
| Bob | Role A | Role B | 2024/02/01 |
| Arthur | Role A | Role C | 2024/01/04 |
| Jane | Role B | Role C | 2024/01/31 |
| Mary | Role A | Role D | 2024/02/12 |
| Liz | Role B | Role F | 2024/02/21 |
| Phoebe | Role C | Role D | 2023/11/21 |
| Mike | Role E | 2024/02/15 |
| Rick | Role D | Role E | 2024/01/13 |
| Hilary | Role F | 2024/01/11 |
现有代码
# Define function to check if a value matches any of the filter values def matches_filter(value): value_lower = value.lower() for filter_value in value_lower.split("|"): filter_value_lower = filter_value.lower() for fvals in fltr_values: if fvals.lower() in filter_value_lower: return fvals.lower() return None # Apply filter # filtered_df = df[df[fltr_field].apply(matches_filter)] df[fltr_field + "_matched"] = df[fltr_field].apply(matches_filter)
需求与期望结果
当传入过滤值为"Role B"和"Role D"时,需要:
- 筛选出角色列包含
Role B或Role D的行 - 将角色列的内容替换为匹配到的过滤值(保留原格式,如
Role B而非小写)
期望结果:
| 姓名 | 角色 | 最后登录日期 |
|---|---|---|
| Phil | Role B | 2024/01/01 |
| Bob | Role B | 2024/02/01 |
| Jane | Role B | 2024/01/31 |
| Mary | Role D | 2024/02/12 |
| Liz | Role B | 2024/02/21 |
| Phoebe | Role D | 2023/11/21 |
| Rick | Role D | 2024/01/13 |
修改方案
现有代码存在三个问题:返回值为小写格式丢失原样式、仅新增匹配列未替换原列、未过滤无匹配的行。需做以下调整:
1. 修正匹配函数的返回逻辑
处理角色分割后的空格问题,返回原始格式的过滤值而非小写:
def matches_filter(value): # 分割角色并去除每个角色的前后空格 roles = [role.strip() for role in value.split("|")] for role in roles: for fval in fltr_values: # 不区分大小写匹配 if role.lower() == fval.lower(): return fval # 返回原始过滤值,保留格式 return None
2. 替换原列并过滤无效行
直接覆盖原角色列,同时删除无匹配结果的行:
# 应用匹配逻辑替换原列 df[fltr_field] = df[fltr_field].apply(matches_filter) # 过滤掉无匹配的行 df = df.dropna(subset=[fltr_field])
完整修改后代码
# 定义匹配函数 def matches_filter(value): roles = [role.strip() for role in value.split("|")] for role in roles: for fval in fltr_values: if role.lower() == fval.lower(): return fval return None # 设置过滤参数 fltr_field = "角色" fltr_values = ["Role B", "Role D"] # 应用匹配并替换列值 df[fltr_field] = df[fltr_field].apply(matches_filter) # 过滤无匹配的行 df = df.dropna(subset=[fltr_field])
内容的提问来源于stack exchange,提问作者Marcus Webb
相关产品推荐
相关产品推荐

