
本文介绍如何使用 Pandas 对宽格式频谱 CSV 数据进行时间维度下采样——将原始 0.25 秒间隔的列压缩为 1 秒间隔,核心方法是转置后利用 .resample("1s").mean() 实现精准时间聚合。
本文介绍如何使用 pandas 对宽格式频谱 csv 数据进行时间维度下采样——将原始 0.25 秒间隔的列压缩为 1 秒间隔,核心方法是转置后利用 `.resample("1s").mean()` 实现精准时间聚合。
在射频信号处理中,原始采集数据常以“频率×时间”宽表形式存储:行代表离散频率点(如 200 行),列代表等间隔时间戳(如 3600 列,步长 0.25 秒)。当需降低时间分辨率(例如从 4 Hz → 1 Hz,即每 4 列合并为 1 列),直接对 DataFrame 按列分组求均值虽可行,但易出错且难以泛化。Pandas 最优雅、最鲁棒的解决方案是将时间信息转化为 DatetimeIndex,并借助 resample() 进行语义化重采样。
✅ 正确做法:用 resample() 实现时间感知下采样
关键前提:时间列必须作为索引(DatetimeIndex)。若原始 CSV 中时间仅是普通列名(如 "t0", "t1"),需先构造对应的时间序列索引:
import pandas as pd
import numpy as np
# 假设已读取原始数据(3600 列,每列代表 0.25 秒)
df = pd.read_csv("spectra.csv", index_col=0) # 频率为行索引,时间为列名
# 构造时间索引:从 2025-04-01 开始,共 3600 个 250ms 间隔
time_index = pd.date_range("2025-04-01", periods=df.shape[1], freq="250ms")
# 将列名替换为时间索引(关键步骤!)
df.columns = time_index
# 执行下采样:转置 → 按 1 秒重采样 → 再转置还原结构
df_downsampled = df.T.resample("1S").mean().T
print(f"原始形状: {df.shape} → 下采样后: {df_downsampled.shape}")
# 输出: 原始形状: (200, 3600) → 下采样后: (200, 900)
? 为什么必须转置?
resample()默认作用于行索引(即时间轴),而你的“时间”在列上。因此需先.T将时间变为行索引,重采样后再.T恢复为“频率×时间”结构。这是 Pandas 2.0+ 的标准范式(旧版axis=1参数已弃用)。
? 验证逻辑:手动对比小样本
为确认结果正确性,可截取前 8 列(2 秒内,含 8 个 0.25s 点)验证:
# 提取前两行(两个频率)、前八列(2秒)
df_mini = df.iloc[:2, :8].T # 转置后:8 行时间 × 2 列频率
print("原始 8 个时间点:")
print(df_mini)
# 重采样(每秒一组)
result = df_mini.resample("1S").mean()
print("\n重采样后(每秒均值):")
print(result)
输出将清晰显示:第 1 行(2025-04-01 00:00:00)是前 4 个 0.25s 值的均值,第 2 行(2025-04-01 00:00:01)是后 4 个值的均值——完全符合“每 4 列合并”的需求。
⚠️ 注意事项与最佳实践
-
索引必须严格等距:
freq="250ms"必须与实际列间隔一致,否则resample()可能跳过或重复采样; -
缺失值处理:若存在 NaN,
resample().mean()默认跳过(skipna=True),如需保留全 NaN 组,可加参数min_periods=4; -
其他聚合方式:除
.mean()外,还可使用.median()、.max()或自定义函数(如agg({'col1': 'mean', 'col2': 'std'})); -
内存优化:对超大文件,建议用
chunksize分块读取,或改用xarray处理多维科学数据。
此方法不仅准确、可读性强,还天然支持时间对齐、时区转换等高级操作,是处理时序频谱数据的工业级推荐方案。










