如何高效基于LFrame聚合Pandas DataFrame(优化大CSV处理)
高效汇总CSV数据至Pandas DataFrame的优化方案
问题背景
我有一个40-50MB的CSV文件,需将其汇总为Pandas DataFrame。新DataFrame基于单调递增但存在重复值的LFrame字段(每个时间步对应多条记录),部分字段需求和,重复字段取首个值。当前用列表推导式实现但运行缓慢,现有代码如下:
new_File = pd.DataFrame({"LFrame": pfd_df.LFrame.unique(), "Num_Channels": [ pfd_df[pfd_df.LFrame == lf].num_signals.sum() for lf in pfd_df.LFrame.unique()], "Date_Time": [pfd_df[pfd_df.LFrame == lf]["Date_Time"].iloc[0] for lf in pfd_df.LFrame.unique()], "run_time": [pfd_df[pfd_df.LFrame == lf].run_time.iloc[0] for lf in pfd_df.LFrame.unique()], "az": [pfd_df[pfd_df.LFrame == lf].az.iloc[0] for lf in pfd_df.LFrame.unique()], "el": [pfd_df[pfd_df.LFrame == lf].el.iloc[0] for lf in pfd_df.LFrame.unique()], "distance": [pfd_df[pfd_df.LFrame == lf].distance.iloc[0] for lf in pfd_df.LFrame.unique()], "pass_ID": [pfd_df[pfd_df.LFrame == lf].pass_ID.iloc[0] for lf in pfd_df.LFrame.unique()], "SV_ID": [pfd_df[pfd_df.LFrame == lf].SV_ID.iloc[0] for lf in pfd_df.LFrame.unique()], "PFD": [pfd_df[pfd_df.LFrame == lf].pfd.sum() * (8.28/90) / (1e-26 * 41667) for lf in pfd_df.LFrame.unique()] })
优化方案
使用Pandas原生的groupby+agg方法,这是矢量化操作,避免了循环切片的重复开销,处理中等数据集时性能会大幅提升:
# 定义各字段的聚合规则 aggregation_rules = { 'num_signals': 'sum', 'Date_Time': 'first', 'run_time': 'first', 'az': 'first', 'el': 'first', 'distance': 'first', 'pass_ID': 'first', 'SV_ID': 'first', 'pfd': lambda series: series.sum() * (8.28/90) / (1e-26 * 41667) } # 按LFrame分组并执行聚合,保留LFrame作为列而非索引 new_File = pfd_df.groupby('LFrame', as_index=False).agg(aggregation_rules) # 重命名列名以匹配需求 new_File.rename(columns={ 'num_signals': 'Num_Channels', 'pfd': 'PFD' }, inplace=True)
优化原理
原代码通过列表推导式循环每个唯一的LFrame,每次循环都要对原DataFrame进行切片筛选,这会产生大量重复计算和内存开销。而groupby是Pandas底层优化的操作,一次性完成分组和聚合,避免了重复切片的损耗,在处理40-50MB的数据集时,运行速度会有数倍甚至数十倍的提升。
内容的提问来源于stack exchange,提问作者earnric
相关产品推荐
相关产品推荐

