如何高效生成含唯一DestName及PAYMENT计数的Pandas DataFrame?
高效实现目标DataFrame(避免循环与索引匹配错误)
错误原因说明
你最初的无循环代码触发ValueError: Can only compare identically-labeled Series objects,是因为df['nameDest']与cust_df.DestName的索引不一致,Pandas在执行==比较时会严格检查索引对齐,导致无法完成逐元素的匹配逻辑。
最优实现代码
利用Pandas的矢量化分组统计功能,无需循环即可高效完成需求:
import pandas as pd def exercise_custom(df): # 统计每个nameDest的PAYMENT记录数 payment_stats = df[df['type'] == 'PAYMENT']['nameDest'].value_counts().reset_index() payment_stats.columns = ['DestName', 'Payment_Count'] # 构建包含所有非空去重nameDest的基础DataFrame dest_names = pd.DataFrame(df['nameDest'].dropna().unique(), columns=['DestName']) # 左连接补全所有DestName,无PAYMENT记录的填充0 cust_df = dest_names.merge(payment_stats, on='DestName', how='left').fillna(0) # 转换为整数类型(可选,根据数据需求调整) cust_df['Payment_Count'] = cust_df['Payment_Count'].astype(int) display(cust_df.head(5)) return cust_df
方案优势
- 性能高效:
value_counts()和merge()都是Pandas底层优化的矢量化操作,时间复杂度为O(M)(M为原DataFrame行数),相比循环的O(N*M)(N为去重DestName数量),处理大数据集时性能提升显著。 - 逻辑简洁:左连接自动保留所有目标
DestName,无需额外判断补0,代码可读性强。
等价实现:groupby方式
如果更倾向于分组统计的直观逻辑,也可以用groupby替代:
def exercise_custom(df): # 分组统计PAYMENT记录数 grouped = df[df['type'] == 'PAYMENT'].groupby('nameDest').size().reset_index(name='Payment_Count') # 合并所有去重DestName并补0 dest_names = pd.DataFrame(df['nameDest'].dropna().unique(), columns=['DestName']) cust_df = dest_names.merge(grouped, on='DestName', how='left').fillna(0).astype({'Payment_Count': int}) display(cust_df.head(5)) return cust_df
循环代码性能问题解析
你写的循环代码效率低下的核心原因是:每次遍历DestName时都要对整个原DataFrame执行筛选操作,相当于重复进行了N次全表扫描,当数据集较大时,这种操作会导致运行时间急剧增加。而矢量化操作仅需遍历原DataFrame一次即可完成统计,性能差距明显。
内容的提问来源于stack exchange,提问作者Eric Kidder
相关产品推荐
相关产品推荐

