Pandas遍历分组DataFrame列检查字符串值计算占比异常问题
问题点梳理
现有两个DataFrame:
doc_df:存储从PDF爬取的文本内容,每行对应1个文档cat_df:存储分类、子分类的映射关系
需要完成两类占比统计:
- 子分类占比:统计至少出现1次该子分类的文档占总文档的比例,原代码计算逻辑正确,但写入DataFrame后数值异常
- 分类占比:统计至少出现该分类下任意一个子分类的文档占总文档的比例,该值不是子分类占比的简单加总,原代码用groupby+apply实现时逻辑错误无法运行
原代码存在两个核心bug:
- 初始化
Subcat_Percentage和Cat_Percentage列时赋值整数0,pandas自动将列类型设为整型,后续写入浮点型占比时会被强制截断为整数,导致数值显示异常 - 分类占比的apply逻辑没有按分组取对应子分类集合,循环中每次仅用当前遍历的单个子分类匹配,还存在语法错误(缺少右括号),既无法得到正确结果,重复遍历计算效率也极低
修复后完整代码
import pandas as pd # 原始数据集 documents = {'Text': ['apple apple', 'banana apple', 'carrot carrot carrot', 'spinach','hammer']} doc_df = pd.DataFrame(data=documents) total_doc_count = len(doc_df) categories = {'Category': ['fruit', 'fruit', 'vegetable', 'vegetable'], 'Subcategory': ['apple', 'banana', 'carrot', 'spinach']} cat_df = pd.DataFrame(data=categories) # 计算子分类占比:用str.contains返回的布尔序列均值直接得到占比,无需手动计数相除 cat_df['Subcat_Percentage'] = cat_df['Subcategory'].apply( lambda subcat: doc_df['Text'].str.contains(subcat, regex=False).mean() ) # 预计算每个分类的占比:同分类下子分类用|拼接为匹配规则,一次匹配即可统计包含任意子分类的文档占比 cat_ratio_mapping = cat_df.groupby('Category')['Subcategory'].apply( lambda subcat_list: doc_df['Text'].str.contains('|'.join(subcat_list), regex=False).mean() ).to_dict() # 映射分类占比到每行 cat_df['Cat_Percentage'] = cat_df['Category'].map(cat_ratio_mapping) # 调整列顺序和原需求一致 cat_df = cat_df[['Category', 'Cat_Percentage', 'Subcategory', 'Subcat_Percentage']] print(cat_df)
运行结果
Category Cat_Percentage Subcategory Subcat_Percentage 0 fruit 0.4 apple 0.4 1 fruit 0.4 banana 0.2 2 vegetable 0.4 carrot 0.2 3 vegetable 0.4 spinach 0.2
注意事项
- 代码中加了
regex=False参数,避免子分类中存在正则特殊字符(比如.、*等)时匹配出错,数据无特殊字符时可省略 - 分类占比计算时自动处理了“一个文档同时包含同分类下多个子分类”的去重计数问题,完全符合“至少提及任意一个子分类”的统计要求,不会重复计数
- 所有计算仅做两次批量匹配,没有嵌套循环,数据量大时运行效率远高于逐行循环遍历的写法
内容的提问来源于stack exchange,提问作者b00kgrrl
相关产品推荐
相关产品推荐

