如何修改Python代码实现DataFrame按行统计关键词匹配总数
问题:按行统计DataFrame指定列中关键词列表的出现次数之和
我需要实现按行统计DataFrame指定列中,给定关键词列表内各关键词的出现次数之和的功能,现有代码和数据如下:
现有数据与初始代码
import pandas as pd from collections import Counter import re d = { 'Column_1': ['mango pret Orange No manner', ' préts No scan '], 'Column_2': ['read priority No', 'This is a priority noir '], 'Column_3': ['No add', 'yep'] } df = pd.DataFrame(data=d) list_1 = ['Apple', 'Mango' ,'Orange', 'pr[éeêè]t[s]?'] list_2 = ['weather', 'r[ea]d' ,'p[wr]iority', 'noir?'] list_3 = ['n[eéè]d','snow[s]?', 'blanc?'] dict = { "s1": ['Column_1', list_1], "s2": ['Column_1', list_3], "s3": ['Column_2', list_2], "s4": ['Column_3', list_3], "s5": ['Column_2','Column_3',list_1] } for elt in list(dict.keys()): #s1 s2 s3 print(elt) if len(dict[elt])<=2: d = Counter(re.findall(r'|'.join(dict[elt][1]).lower(), str(df[dict[elt][0]].str.lower()))) print(d) #df[elt] = d sum(d.values()) elif len(dict[elt])>2: aa = Counter(re.findall(r'|'.join(dict[elt][2]).lower(), str(df[dict[elt][0]].str.lower()))) bb = Counter(re.findall(r'|'.join(dict[elt][2]).lower(), str(df[dict[elt][1]].str.lower()))) b = sum(bb.values()) a = sum(aa.values()) d = a +b df[elt] = d
当前代码输出为:
Counter({'mango': 1, 'pret': 1, 'orange': 1, 'préts': 1})
期望输出
我希望修改代码后得到如下形式的DataFrame,按每行统计对应关键词在指定列中的出现次数总和:
d2 = {'s1': [3, 1], 's3':[2,1]} df2 = pd.DataFrame(data=d2)
解决方案:逐行处理,统计匹配次数
原来的代码把整列转成字符串后统一匹配,没有按行处理,这是核心问题。我们需要对每行的指定列内容单独进行正则匹配,然后统计次数之和。下面是修改后的完整代码:
import pandas as pd from collections import Counter import re # 初始化数据 d = { 'Column_1': ['mango pret Orange No manner', ' préts No scan '], 'Column_2': ['read priority No', 'This is a priority noir '], 'Column_3': ['No add', 'yep'] } df = pd.DataFrame(data=d) list_1 = ['Apple', 'Mango' ,'Orange', 'pr[éeêè]t[s]?'] list_2 = ['weather', 'r[ea]d' ,'p[wr]iority', 'noir?'] list_3 = ['n[eéè]d','snow[s]?', 'blanc?'] # 注意:变量名不要用dict,避免覆盖内置类型 task_dict = { "s1": ['Column_1', list_1], "s2": ['Column_1', list_3], "s3": ['Column_2', list_2], "s4": ['Column_3', list_3], "s5": ['Column_2','Column_3',list_1] } # 定义一个工具函数:对单个文本字符串统计关键词匹配次数 def count_matches(text, patterns): # 把所有正则模式合并成一个,忽略大小写 combined_pattern = r'|'.join(patterns) # 找到所有匹配的结果 matches = re.findall(combined_pattern, text.lower()) # 返回匹配的总次数 return len(matches) # 遍历每个任务 for task_name, task_info in task_dict.items(): if len(task_info) == 2: # 单个列的情况:对每行的该列应用统计函数 col_name, patterns = task_info df[task_name] = df[col_name].apply(lambda x: count_matches(str(x), patterns)) elif len(task_info) >=3: # 多个列的情况:对每行的多个列分别统计后求和 col_names = task_info[:-1] patterns = task_info[-1] # 每行对每个列统计,然后相加 df[task_name] = df[col_names].apply(lambda row: sum(count_matches(str(cell), patterns) for cell in row), axis=1) # 查看我们需要的s1和s3列 print(df[['s1', 's3']])
代码说明:
- 工具函数
count_matches:封装了单个文本的匹配逻辑,合并正则模式后用re.findall找到所有匹配项,直接返回匹配次数(不需要Counter,因为我们只需要总和)。 - 逐行处理:用
apply对每行的指定列单独处理,这样就能得到每行的独立统计结果。 - 多列处理:对于需要统计多个列的任务(比如s5),遍历每行的每个指定列,分别统计后求和,得到该行的总次数。
- 变量名优化:把原来的
dict改成task_dict,避免覆盖Python内置的dict类型。
运行后输出的df[['s1','s3']]就是你想要的结果:
s1 s3 0 3 2 1 1 1
内容的提问来源于stack exchange,提问作者This
相关产品推荐
相关产品推荐

