Pandas如何基于两字段唯一组合转换DataFrame(替代for循环)
问题说明
你需要生成A列唯一值与指定B列候选值的全量组合,匹配原DataFrame中对应的行数据,替代低效的嵌套for循环实现。
实现方案
直接用pandas原生的笛卡尔积生成+重索引方法实现,无需手写循环,性能更高逻辑更简洁:
注意不要用
list作为变量名,会覆盖Python内置的list类型,建议改名。
import pandas as pd # 原数据 df = pd.DataFrame({'A' : ['A','B','C','D','E','F','G','H','I'], 'B' : ['B','C','D','E','F','G','H','I','J'], 'C' : ['C','D','E','F','G','H','I','J','J'], 'D' : ['D','E','F','G','H','I','J','J','J'], 'E' : ['E','F','G','H','I','J','A','B','C'], 'F' : ['B','C','D','B','C','D','B','C','D'], }) # 要匹配的B列目标值,原变量名list改名为target_b避免冲突 target_b = ['A','B','C','D'] # 1. 生成A列唯一值、目标B值的所有组合 unique_a = df['A'].unique() full_comb = pd.MultiIndex.from_product( [unique_a, target_b], names=['A', 'B'] ) # 2. 原数据按A、B去重,仅保留每个组合的第一行(和原逻辑取iloc[0]一致) df_dedup = df.drop_duplicates(subset=['A', 'B']).set_index(['A', 'B']) # 3. 重索引匹配全量组合,匹配不到的行自动填充空值 result_df = df_dedup.reindex(full_comb).reset_index() # 4. 计算每个(A,B)组合的出现次数、匹配状态 counts = df.groupby(['A', 'B']).size() result_df['count'] = result_df.set_index(['A','B']).index.map(counts).fillna(0).astype(int) result_df['status'] = result_df['count'].apply(lambda x: 'found' if x > 0 else 'empty') # 5. 空值替换为空字符串,和预期输出格式对齐 result_df[['C','D','E','F']] = result_df[['C','D','E','F']].fillna('')
结果验证
如果需要生成示例里的逐行打印字符串格式,加一行代码即可:
# 生成和原循环打印格式完全一致的字符串列 result_df['print_line'] = result_df.apply( lambda r: f"{r['A']}:{r['B']},{r['C']},{r['D']},{r['E']},{r['F']},{r['status']},{r['count']}", axis=1 ) # 打印查看 for line in result_df['print_line']: print(line)
输出结果和给出的示例完全一致,没有冗余循环,数据量越大性能优势越明显。
内容的提问来源于stack exchange,提问作者Patrick C
相关产品推荐
相关产品推荐

