Pandas DataFrame按分类字典匹配值生成对应类别列的实现问题
解决方法
问题原因
你当前代码的核心问题有两个:
- 每次匹配到分类对应的name时直接对列赋值,后续匹配到的同分类name会直接覆盖已有的值,自然无法实现多值拼接
- 将A列的字典列表强制转成字符串后用
str.contains匹配,可能出现子串误匹配的问题(比如存在name为"sport news"时,会同时匹配到sport和news两个分类)
优化后实现代码
推荐直接处理原始的A列字典列表结构,避免字符串匹配的误差,代码如下:
import pandas as pd import numpy as np # 你的原始DataFrame df = pd.DataFrame([ {'ID': 1,'A': [{'name': 'lifestyle'}, {'name': 'economy'}, {'name': 'politics'}, {'name': 'climate & environment'}]}, {'ID': 2,'A': [{'name': 'sport'}]}, {'ID': 3,'A': [{'name': 'climate & environment'}]}, {'ID': 4,'A': [{'name': 'sport'}]}, {'ID': 5,'A': [{'name': 'politics'}, {'name': 'world'}]}, {'ID': 6,'A': [{'name': 'economy'}, {'name': 'politics'}]} ]) # 1. 读取分类字典 category_map = {} with open("categories.txt", "r") as file: for line in file: key, value = line.strip().split(":") category_map[key.strip()] = value.strip() # 2. 定义行处理函数 def process_row(row): # 初始化各分类的结果存储列表 res = {'cat1': [], 'cat2': [], 'cat3': [], 'cat4': []} # 遍历A列的每个字典提取name并分类 for item in row['A']: name = item['name'] if name in category_map: cat = category_map[name] res[cat].append(name) # 列表转逗号拼接字符串,空列表替换为nan for k in res: res[k] = ', '.join(res[k]) if res[k] else np.nan return pd.Series(res) # 3. 应用函数生成新列,合并到原DataFrame df = pd.concat([df[['ID']], df.apply(process_row, axis=1)], axis=1)
注:你给出的期望输出中第6行cat1列的'politics'实际属于分类cat2,属于笔误,上述代码运行后会自动纠正为正确的分类归属
基于原有逻辑的修改方案
如果你不想改动原有A列转字符串的逻辑,只需要将直接赋值改为字符串拼接即可:
# 提前初始化所有分类列为空字符串 for cat in ['cat1','cat2','cat3','cat4']: df[cat] = '' for k, v in d.items(): mask = df['A'].str.contains(k) # 已有值则追加,无值则直接赋值 df.loc[mask, v] = df.loc[mask, v].apply(lambda x: x + ', ' + k if x else k) # 空字符串统一替换为nan df[['cat1','cat2','cat3','cat4']] = df[['cat1','cat2','cat3','cat4']].replace('', np.nan)
内容的提问来源于stack exchange,提问作者iittala
相关产品推荐
相关产品推荐

