Polars时间序列重采样与插值:仅填充3分钟内小间隙
时间序列插值:Polars实现仅填充≤3分钟间隙的方案
问题背景
需处理时间序列数据集,要求仅填充时长不超过3分钟的数据间隙,超过3分钟的间隙保留为null。使用Polars的upsample操作后生成大量空值,直接调用interpolate()会对全量空值插值,不符合需求。
解决方案
以下是对齐Pandas逻辑的Polars实现步骤:
1. 数据排序与平滑处理
先确保时间序列有序,再对非时间列应用Savgol滤波平滑:
import polars as pl from scipy.signal import savgol_filter # 加载并解析时间列(替换为你的数据路径) df = pl.read_csv("your_data.csv", parse_dates=["utc"]) # 按时间排序 df = df.sort("utc") # 对非utc列应用Savgol滤波 df_smoothed = df.with_columns( pl.exclude("utc").map_batches( lambda col: savgol_filter(col.to_numpy(), window_length=31, polyorder=3) ) )
2. 重采样生成均匀时间序列
通过upsample生成10秒间隔的时间序列:
# 按10秒间隔重采样 df_upsampled = df_smoothed.upsample(time_column="utc", every="10s")
3. 生成可填充间隙掩码(核心步骤)
计算每个空值位置的前后非空时间差,判断是否属于≤3分钟的可填充范围:
MAX_DELTA = pl.duration(minutes=3) df_masked = df_upsampled.with_columns( # 获取前一个非空的时间戳 prev_valid_time=pl.col("utc").forward_fill(), # 获取后一个非空的时间戳 next_valid_time=pl.col("utc").backward_fill() ).with_columns( # 计算当前时间与前后有效时间的差值 delta_prev=pl.col("utc") - pl.col("prev_valid_time"), delta_next=pl.col("next_valid_time") - pl.col("utc"), # 判断是否为可填充间隙:前后差值均≤3分钟,且当前值为空 can_interpolate=pl.when( (pl.col("delta_prev") <= MAX_DELTA) & (pl.col("delta_next") <= MAX_DELTA) & pl.any(pl.exclude("utc", "prev_valid_time", "next_valid_time").is_null()) ).then(True).otherwise(False) )
4. 条件插值
仅对can_interpolate为True的位置进行插值,其余空值保留:
# 对数值列线性插值,仅保留符合条件的填充结果 df_final = df_masked.with_columns( pl.exclude("utc", "prev_valid_time", "next_valid_time", "delta_prev", "delta_next", "can_interpolate") .interpolate(method="linear") .where(pl.col("can_interpolate")) ).drop(["prev_valid_time", "next_valid_time", "delta_prev", "delta_next", "can_interpolate"])
关键说明
- 平滑处理:
map_batches直接对列数组应用滤波,无需explode(此前的错误操作导致数据结构异常) - 掩码逻辑:通过
forward_fill和backward_fill定位前后有效数据的时间戳,计算时间差筛选可填充间隙 - 条件插值:先全量插值,再用
where保留符合要求的填充结果,确保超过3分钟的间隙仍为null
内容的提问来源于stack exchange,提问作者Vyas Giridharan
相关产品推荐
相关产品推荐

