
本文介绍如何使用pandas高效批量读取101个结构相同的csv文件,对第二列(如光谱功率密度s)逐元素平方后,按行号(即相同频率位置)跨文件求平均,最终获得平滑的统计谱线。
本文介绍如何使用pandas高效批量读取101个结构相同的csv文件,对第二列(如光谱功率密度s)逐元素平方后,按行号(即相同频率位置)跨文件求平均,最终获得平滑的统计谱线。
在科学数据处理中,常需对大量重复实验生成的CSV文件进行统计聚合——例如光谱分析中,多个测量文件对应同一频率轴(第一列,如W或w),第二列(如S)为谱密度值。目标不是按文件平均,而是对每个频率点(即每行),收集所有101个文件中该行的S值,先平方再求均值,从而得到稳健的平均谱功率密度曲线。
但直接循环读取+手动对齐行会低效且易出错。推荐采用“纵向拼接→分组→向量化计算”的策略,兼顾可读性与性能:
✅ 正确做法:按行对齐 + 向量化平方均值
关键在于:所有CSV文件具有完全一致的行数(10001行)和相同的第一列(频率W)顺序。此时最高效的方式是——不按文件分组,而按行索引分组:
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
import os
import pandas as pd
import numpy as np
# 1. 配置路径(请替换为你的实际路径)
csv_folder = r'C:\Users\Den\Desktop\SPD'
csv_files = [os.path.join(csv_folder, f) for f in os.listdir(csv_folder)
if f.endswith('.csv') and f.startswith('tek')]
print(f"共找到 {len(csv_files)} 个CSV文件")
# 2. 批量读取并拼接:每行保留原始索引,便于后续按行聚合
dataframes = []
for file in csv_files:
df = pd.read_csv(file, sep=';', usecols=['W', 'S']) # 显式指定列,提升速度
df['file_id'] = len(dataframes) # 可选:标记来源文件
dataframes.append(df)
# 沿行方向拼接(axis=0),保留原始行索引(0~10000重复101次)
mega_df = pd.concat(dataframes, ignore_index=False) # 关键:ignore_index=False!
# 3. 对每个频率位置(即原始行号)计算 S² 的均值
# 假设所有文件的'W'列严格对齐,则直接按索引分组即可
# 若需严格校验频率一致性,可加 assert np.allclose(mega_df.groupby(level=0)['W'].nunique(), 1)
s_squared = mega_df['S'] ** 2
mean_s_sq_by_row = s_squared.groupby(level=0).mean() # 按原始行索引分组求均值
# 4. 构建最终结果:频率W(取任一文件首份) + 平均平方谱密度
freq_ref = pd.read_csv(csv_files[0], sep=';', usecols=['W'])['W']
result_df = pd.DataFrame({
'W': freq_ref.values,
'S_mean_sq': mean_s_sq_by_row.values
})
print("结果形状:", result_df.shape) # 应为 (10001, 2)⚠️ 注意事项与优化建议
- 索引对齐是核心:pd.concat(..., ignore_index=False) 保留原始行号(0–10000),使相同行号天然对应同一频率点。若文件行数不一致,需先校验或插值对齐。
- 内存友好:避免一次性加载全部S列再平方——上述代码中s_squared是惰性计算的Series,groupby.mean()内部高度优化。
- 列名适配:示例中假设列为'W'和'S';请根据实际CSV头调整(可用df.columns.tolist()检查)。
-
绘图可视化:
import matplotlib.pyplot as plt plt.figure(figsize=(10, 6)) plt.plot(result_df['W'], result_df['S_mean_sq'], label='Mean(S²) across 101 files') plt.xlabel('Frequency (W)') plt.ylabel('Mean Squared Spectral Density') plt.title('Averaged Power Spectrum') plt.grid(True) plt.legend() plt.show()
? 总结
该方案摒弃了低效的嵌套循环,利用pandas的concat与groupby天然支持“跨文件同位置聚合”,代码简洁、逻辑清晰、运行高效。最终输出的result_df即为你所需的10001点平均谱线——它消除了单次测量噪声,更真实反映系统频谱特性。
立即学习“Python免费学习笔记(深入)”;

















