Pandas带计数器两列嵌套循环活动统计及报错解决
问题场景
- 基础数据结构:
- 活动分类表
df1:共两列,Type为活动大类,取值包含Sport、Studies两类;Activity为具体活动项,取值包含rowing、Surfing、Basketball、Dancing、science、Math、History等,实际业务场景下共30个活动子类别 - 调研数据表
df2:每条记录为学生活动参与的自然语言描述,格式类似Sarah does Basketball and Math
- 活动分类表
- 计算需求:统计每条调研文本中,分属Sport、Studies大类的活动数量,最终输出包含三列的结果表:
Student(原始调研文本)、Sports(运动类活动匹配计数)、Studies(学业类活动匹配计数) - 初始实现踩坑:最初尝试嵌套循环遍历分类表逐句匹配、手动创建分类列表/子表实现,代码冗余且效果差;后续写的测试代码运行触发类型错误,无法定位问题。
报错原因
- 核心映射逻辑错误:测试代码中把
activity_type构造为「大类名: 对应活动列表」的字典结构,但后续匹配逻辑是拿拆分后的单个单词直接调用activity_type.get(activity),该字典的键是大类名,根本无法通过单个活动名查询到所属分类,逻辑完全不匹配。 - 类型兼容问题:旧版本pandas的
pd.json_normalize在处理序列中存储的Counter对象时,会触发隐式类型转换失败,抛出TypeError: int() argument must be a string, a bytes-like object or a number, not 'Counter'报错。
可行实现方案
核心思路是先构造单个活动名(统一转小写做归一化)到所属大类的映射字典,再逐行拆分调研文本做匹配计数,避免多层嵌套循环,代码可维护性更高,适配30个甚至更多活动子类的扩展需求。
import pandas as pd from collections import Counter # 读取本地数据文件 df1 = pd.read_csv('df1.csv') df2 = pd.read_csv('df2.csv') # 构造正确的活动-大类映射字典,统一转小写消除大小写匹配差异 activity_type_map = dict(zip( df1['Activity'].str.strip().str.lower(), df1['Type'].str.strip().str.lower() )) # 定义单条文本的活动分类计数函数 def count_type(text): words = text.strip().lower().split() counter = Counter() for word in words: # 命中活动映射则对应大类计数+1 if word in activity_type_map: counter[activity_type_map[word]] += 1 return counter # 批量计算所有文本的分类计数,展开为DataFrame count_result = pd.json_normalize(df2['Student'].apply(count_type)) # 空值填0,转为整数类型,列名对齐需求格式 count_result = count_result.fillna(0).astype(int).rename(columns={ 'sport': 'Sports', 'studies': 'Studies' }) # 拼接原始文本和计数结果,得到最终表 final_df = pd.concat([df2, count_result], axis=1)
注意:如果后续活动项存在多词组的情况(比如
table tennis),直接按空格拆分单词会导致匹配失败,此时可将活动列表按字符串长度从长到短排序,通过正则匹配或字符串遍历的方式做计数,避免拆分漏匹配。
内容的提问来源于stack exchange,提问作者Jessica warren
相关产品推荐
相关产品推荐

