如何在Pandas DataFrame中根据列内容匹配字典关键词生成标记列?
问题:基于关键词为Pandas DataFrame添加分类标签
需要给存储课程挑战分类的Pandas DataFrame每行标记linux、windows或primer,已定义如下关键词字典:
import pandas as pd topic_keywords_dict = { 'Linux': { 'identification':['linux'], 'topic': [ 'bash','boot','process','auditing' ]}, 'Windows': { 'identification':['windows','memory'], 'topic': [ 'boot','process','artifacts','memory','active_directory','sysinternal' ]}, 'Primer': { 'identification':['primer'], 'topic': [ 'kernel','CLI','registry','process','NTFS','boot','auditing','security','active_directory','networking','surveys' ]} }
目标DataFrame定义如下:
challenge_count_df = pd.DataFrame({'Challenge': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], 'Count' : [32, 22, 40, 12, 10, 60, 32, 22, 44, 90], 'Value' : ["0","5","10","15","5","10","5","10","15","10"], 'Category' : ['linux_bash','primer_02','windows_active_directory','basic_linux','linux_kitty','alpha_primer','windows_auditing','linux_logging', 'linux', 'primer']})
原DataFrame结构:
>>> challenge_count_df Challenge Count Value Category 0 A 32 0 linux_bash 1 B 22 5 primer_02 2 C 40 10 windows_active_directory 3 D 12 15 basic_linux 4 E 10 5 linux_kitty 5 F 60 10 alpha_primer 6 G 32 5 windows_auditing 7 H 22 10 linux_logging 8 I 44 15 linux 9 J 90 10 primer
尝试了以下代码但出现错误:
challenge_count_df[challenge_count_df['Category'].contains('|'.join(topic_keywords_dict[dict_key]['identification']))]
以及错误的lambda写法:
challenge_count_df['key_dict'] = challenge_count_df['Category'].apply(lambda x: key_dict if x .contains('|'.join(topic_keywords_dict[dict_key]['identification'])) for key_dict in topic_keywords_dict)
预期生成包含key_dict列的结果:
>>> challenge_count_df Challenge Count Value Category key_dict 0 A 32 0 linux_bash linux 1 B 22 5 primer_02 primer 2 C 40 10 windows_active_directory windows 3 D 12 15 basic_linux linux 4 E 10 5 linux_kitty linux 5 F 60 10 alpha_primer primer 6 G 32 5 windows_auditing windows 7 H 22 10 linux_logging linux 8 I 44 15 linux linux 9 J 90 10 primer primer
错误原因分析
- lambda函数仅支持单个表达式,不能直接嵌入
for循环生成式,语法不符合规则 - 字符串对象没有
contains方法,Pandas的str.contains是Series的方法,单个字符串需用in判断或正则匹配 - 循环中
dict_key的作用域问题,无法在lambda内部正确遍历字典键并完成匹配
正确实现方法
方法1:自定义函数结合apply
通过自定义函数遍历关键词字典,匹配后返回对应分类标签:
def get_category(category_str): # 遍历每个分类的关键词配置 for category_key, config in topic_keywords_dict.items(): # 检查当前Category字符串是否包含该分类的识别关键词 for keyword in config['identification']: if keyword in category_str.lower(): return category_key.lower() # 无匹配时返回None(可根据需求修改默认值) return None # 应用函数生成新列 challenge_count_df['key_dict'] = challenge_count_df['Category'].apply(get_category)
方法2:向量化匹配(np.select)
利用np.select实现批量条件判断,效率更高:
import numpy as np # 构建匹配条件列表 conditions = [ # 匹配Linux的识别关键词 challenge_count_df['Category'].str.contains('|'.join(topic_keywords_dict['Linux']['identification']), case=False), # 匹配Windows的识别关键词 challenge_count_df['Category'].str.contains('|'.join(topic_keywords_dict['Windows']['identification']), case=False), # 匹配Primer的识别关键词 challenge_count_df['Category'].str.contains('|'.join(topic_keywords_dict['Primer']['identification']), case=False) ] # 对应条件的标签 choices = ['linux', 'windows', 'primer'] # 生成分类标签列 challenge_count_df['key_dict'] = np.select(conditions, choices, default=None)
方法3:正则提取+映射
通过正则提取匹配的关键词,再映射到对应分类:
import re # 构建所有识别关键词的正则表达式(不区分大小写) all_keywords = [kw for cat in topic_keywords_dict.values() for kw in cat['identification']] pattern = re.compile(r'(' + '|'.join(all_keywords) + ')', flags=re.IGNORECASE) # 提取匹配的关键词 extracted_keyword = challenge_count_df['Category'].str.extract(pattern)[0].str.lower() # 构建关键词到分类的映射表 keyword_to_category = {} for cat_name, config in topic_keywords_dict.items(): for kw in config['identification']: keyword_to_category[kw.lower()] = cat_name.lower() # 映射得到分类标签 challenge_count_df['key_dict'] = extracted_keyword.map(keyword_to_category)
以上三种方法都能生成预期的key_dict列,可根据数据规模和个人习惯选择。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

