You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Pandas创建亚毫秒时间序列并下采样至1500Hz?

问题描述

作为Pandas时间序列新手,我有一小时2500Hz采样的电压数据,需要完成两项操作:

  • A)为数据创建datetime索引/对象
  • B)将其下采样至1500Hz

附示例代码:

original_hz = 1/2500 # 2500 hz
downsample_to_hz = 1/1500 # 1500 hz

# 1 second time index at the two sampling frequencies
time_2500hz = np.arange(0, 1, original_hz) 
time_1500hz = np.arange(0, 1, downsample_to_hz)

# example sine wave of recording at 2500hz
amplitude   = np.sin(time_2500hz)

请问如何对amplitude进行下采样和插值,使其与1500Hz采样的时间索引对齐?优先使用Pandas时间序列方案,也欢迎NumPy示例。

补充:发现Scipy的scipy.signal.decimate函数接近需求,但该函数的抽取因子q需为整数,无法适配所有场景。


解决方案

Pandas时间序列方案

步骤A:创建Datetime索引

假设数据从指定起始时间(示例用2024-01-01 00:00:00)开始,用pd.date_range生成精确的datetime索引,完美匹配2500Hz的采样间隔:

import pandas as pd
import numpy as np

# 1小时2500Hz数据的总采样数
total_samples = 2500 * 3600
start_time = "2024-01-01 00:00:00"

# 生成datetime索引,频率为1/2500秒
dt_index = pd.date_range(start=start_time, periods=total_samples, freq=f"{1/2500}S")

# 构造带索引的DataFrame(用正弦波模拟真实电压数据)
amplitude = np.sin(np.arange(total_samples) * 1/2500 * 2 * np.pi)  # 1Hz正弦波示例
df = pd.DataFrame({"voltage": amplitude}, index=dt_index)

步骤B:下采样至1500Hz

Pandas的resample方法直接支持非整数倍的采样率转换,结合插值即可对齐目标时间点:

# 目标采样频率的周期(1/1500秒)
target_freq = f"{1/1500}S"

# 按目标频率重采样,用线性插值补全数据
downsampled_df = df.resample(target_freq).interpolate(method="linear")

# 验证结果:1小时1500Hz数据应有1500*3600=5,400,000行
print(len(downsampled_df))  # 输出5400000

如果需要避免信号混叠(高频失真),可以先对原始数据做低通滤波,再进行插值:

from scipy.signal import butter, filtfilt

# 设计低通滤波器:截止频率设为目标采样率的奈奎斯特频率(1500Hz/2=750Hz)
def butter_lowpass(cutoff, fs, order=5):
    nyq = 0.5 * fs
    normal_cutoff = cutoff / nyq
    b, a = butter(order, normal_cutoff, btype='low', analog=False)
    return b, a

# 对原始电压数据进行滤波
fs_original = 2500
cutoff_freq = 750
b, a = butter_lowpass(cutoff_freq, fs_original)
df["filtered_voltage"] = filtfilt(b, a, df["voltage"])

# 滤波后再插值下采样
downsampled_filtered_df = df["filtered_voltage"].resample(target_freq).interpolate(method="linear")

NumPy方案

如果不用Pandas,直接基于时间数组进行插值也能实现需求:

步骤A:关联时间与数据

import numpy as np

# 生成1小时的原始时间数组(单位:秒)
time_2500hz = np.arange(0, 3600, 1/2500)
amplitude = np.sin(time_2500hz * 2 * np.pi)  # 1Hz正弦波示例

# 生成目标1500Hz的时间数组
time_1500hz = np.arange(0, 3600, 1/1500)

步骤B:插值对齐

用np.interp进行线性插值,直接将原始数据映射到目标时间点:

# 线性插值得到1500Hz采样的数据
downsampled_amplitude = np.interp(time_1500hz, time_2500hz, amplitude)

# 可选:先滤波再插值,避免混叠
from scipy.signal import butter, filtfilt

fs_original = 2500
cutoff_freq = 750
b, a = butter_lowpass(cutoff_freq, fs_original)
filtered_amplitude = filtfilt(b, a, amplitude)
downsampled_filtered_amplitude = np.interp(time_1500hz, time_2500hz, filtered_amplitude)

关于Scipy decimate的补充

scipy.signal.decimate要求抽取因子q为整数,像2500Hz→1500Hz这种非整数倍的转换(q=5/3)确实无法直接使用。上面的插值+可选滤波方案更通用,既能精准对齐时间点,也能通过前置滤波解决信号混叠问题。


内容的提问来源于stack exchange,提问作者Angus Campbell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 07:20:37