如何检查Pandas行是否包含指定数量的特定字符串
问题描述
现有两个DataFrame:df1(32611行×17列)和df2(6行×17列)。需要针对df2每行的value_counts统计结果,检查df1的每一行是否包含对应数量的指定字符串(例如某行要求包含4个HEX、1个ACP、1个TUR),符合条件的行进行标记,不符合则跳过。
数据示例
df1 数据片段
0 1 2 3 4 5 ... 11 12 13 14 15 16 0 BSO PRV BSI TUR WSP ACP ... HLR HEX HEX None None None 1 BSO PRV BSI TUR WSP ACP ... HLF HLR HEX HEX HEX None 2 BSO PRV BSI HLF HLR TUR ... HEX RSO RSI HEX HEX HEX 3 BSO PRV BSI HLF HLR TUR ... RSO RSI HEX HEX HEX None 4 BSO PRV BSI HLF TUR WSP ... RSO RSI HLR HEX HEX HEX ... ... ... ... ... ... ... ... ... ... ... ... ... 32607 BSO PRV BSI TUR WSP ACP ... HEX None None None None None 32608 BSO PRV BSI TUR WSP ACP ... HEX None None None None None 32609 BSO PRV BSI TUR WSP ACP ... HEX None None None None None 32610 BSO PRV BSI TUR WSP ACP ... HEX None None None None None 32611 BSO PRV BSI TUR WSP ACP ... HEX None None None None None
df2 数据片段
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 ACP HEX HEX HEX HEX TUR NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 2 ACP HEX HEX HEX HEX HEX HEX TUR NaN NaN NaN NaN NaN NaN NaN NaN NaN 3 ACP HEX HEX HEX HEX HEX HEX TUR TUR NaN NaN NaN NaN NaN NaN NaN NaN 4 ACP HEX HEX HEX HEX TUR TUR NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 5 ACP HEX HEX TUR NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 6 ACP HEX HEX TUR TUR NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
示例匹配规则(df2某行的value_counts结果)
HEX 4 ACP 1 TUR 1 Name: 1, dtype: int64
解决方案
直接遍历df1的3万多行效率极低,推荐用向量化操作结合计数匹配实现,以下是两种可行方案:
方案1:基于apply的快速实现
步骤1:预处理df2生成匹配规则
import pandas as pd # 提取df2每行的计数规则,自动忽略NaN/None df2_rules = [] for _, row in df2.iterrows(): cnt = row.value_counts(dropna=True) df2_rules.append(cnt)
步骤2:生成df1每行的计数统计
# 统计df1每行各类别的出现次数 df1_row_counts = df1.apply(lambda row: row.value_counts(dropna=True), axis=1)
步骤3:匹配规则并添加标记
# 为每个规则创建标记列,1表示符合规则,0表示不符合 for rule_idx, rule in enumerate(df2_rules, start=1): match_mask = df1_row_counts.apply( lambda cnt: all(cnt.get(cat, 0) == num for cat, num in rule.items()), axis=1 ) df1[f'match_rule_{rule_idx}'] = match_mask.astype(int)
方案2:高效优化版(适合大数据集)
通过转置统计生成计数矩阵,避免逐行循环,效率提升明显:
# 把df1转成长格式,方便按行统计类别数量 melted_df1 = df1.melt(ignore_index=False, var_name='col', value_name='val').dropna() # 生成每行×每个类别的计数矩阵 count_matrix = pd.crosstab(melted_df1.index, melted_df1['val']) # 遍历规则完成匹配 for rule_idx, rule in enumerate(df2_rules, start=1): # 初始化匹配掩码为全符合 mask = pd.Series([True]*len(df1), index=df1.index) for cat, num in rule.items(): # 检查该类别的计数是否满足要求,更新掩码 cat_counts = count_matrix.get(cat, pd.Series([0]*len(df1), index=df1.index)) mask &= (cat_counts == num) # 添加标记列 df1[f'match_rule_{rule_idx}'] = mask.astype(int)
内容的提问来源于stack exchange,提问作者Tony Sirico
相关产品推荐
相关产品推荐

