想象你是一名气象观测员,住在山脚下的小气象站里。你的日常工作很简单:走到院子里看一眼温度计,在笔记本上写下一行记录。但真实的记录过程远没有想象中干净——自动气象站每 5 分钟吐一条数据,哗哗地像打字机;你的手动笔记本呢,有时半小时记一条,有时因为接电话漏掉一整个下午;同事老李送来的观测记录,用的还是另一套时间刻度。月底一到,气象局要的是一张“每小时一条、时间整整齐齐”的温度报表。 要交出这样一张报表,你必须做三件事:把 5 分钟一条的高频记录“压粗”成 1 小时一条(降采样);把漏掉的时刻根据前后数据“脑补”出来(升采样);把 9:12、9:47 这种参差不齐的时间戳“摆正”到 9:00、9:30 的标准网格上(时间对齐)。这一整套在时间维度上“换记录节奏”的加工手艺,就是时序数据的重采样与对齐技术。
重采样与对齐是时序数据工程的“基础设施”:掌握它,你才能把监控、金融、IoT 等真实世界里的杂乱时间序列,变成模型吃得下的规整数据。这是每一位数据分析师和 AI 建模工程师的基本功。
可视化演示
展示降采样聚合降频、升采样插值补缺与不规则采样均匀化对齐,交互理解时序重采样的三种核心操作。
本节配有交互动效(进入视口后自动加载,约 3KB)。
'+modeData.downsample.caption+'
概念与本质
你是一名气象观测员,住在山脚下的小气象站里。每天的工作听起来简单:去院子里看一眼温度计,在笔记本上写一行记录。但“记录节奏”从来由不得你——自动气象站每 5 分钟吐一条数据,哗哗地像打字机;你手动记录呢,有时半小时一条,有时一忙就是一小时一条。等月底把记录交给气象局时,对方只认一种格式:每小时一条。于是你不得不把数据从一种“记录节奏”硬生生换成另一种。
这种“换节奏”的操作,在时序数据处理里叫作重采样(Resampling)。它的本质是调整时间轴的刻度:把散落在旧刻度上的观测值,映射到一组新的、统一的时间刻度上。如果新刻度比旧刻度更稀疏,也就是从高频走向低频,叫降采样;如果新刻度比旧刻度更密集,从低频走向高频,叫升采样。而在动手重采样之前,还有一个绕不开的前置动作——时间对齐,也就是先把时间戳摆到目标网格上,否则后面的聚合与插值都无从谈起。
衡量记录节奏有两个基本参数:采样间隔 ΔT 与采样频率 f。采样间隔是相邻两条记录的时间差,采样频率是单位时间内记录的次数。高频数据细节丰富,但存储与计算开销都大;低频数据简洁,却对瞬时突变不敏感。重采样的核心,就是在这两者之间做一次可控制的转换。转换前你总要回答三个问题:新刻度定多密、时间窗怎么切、窗内的值如何汇总——这三个问题串起来,就是整篇重采样技术的骨架。
回到气象站:自动站的高频记录像打字机一样哗哗出纸,手动笔记本则稀稀拉拉。重采样就是你手中的“抄表规范”,决定最终用哪种节奏把温度写进报表。概念清楚了,下一步得先把时间戳本身摆正。
- f(采样频率)f 表示单位时间内的记录条数,比如每小时记录 1 条,则 f 等于 1 条每小时。
- ΔT(采样间隔)ΔT 表示相邻两条记录之间的时间差,比如每 5 分钟一条,则 ΔT 等于 5 分钟。
- 倒数关系频率与间隔互为倒数,间隔越小频率越高;重采样就是调整间隔从而改变频率。
时间对齐基础
月底,你要和同事老李合并数据画一条温度曲线。翻开你的笔记本:9:12、9:47、10:03……再看老李的自动站输出:9:00、9:15、9:30……两本记录的时间戳根本对不上,硬画在同一张图上,点与点全错位,曲线变成一团乱麻。
时间对齐(Time Alignment)要解决的就是这个问题:让来自不同来源、不同时刻的记录,落在同一套标准时间网格上。它是所有重采样的前置步骤——时间戳都不齐,谈何聚合与插值?对齐的第一步是时间戳规整:选定目标间隔 Δ 后,把每个原始时间戳向下取整,归入它所在的网格区间。第二步是选择对齐方向:左对齐让窗口标签取区间起点,右对齐让标签取区间终点,这会影响聚合结果挂在哪个时刻上。第三步是索引对齐:以目标网格为索引,把原始数据一一映射上去,落在同一格内的观测自然归为一组。如果数据来自不同时区,还得先统一到时区再做规整,否则“9 点”到底是哪里的 9 点都说不清。
对齐就像把两本笔记本的时间列都统一改成“整点、半点”的刻度。时间轴摆正之后,才轮到真正的重采样——先看把高频数据变稀疏的降采样。
- t_i(原始时间戳)这是某条记录原本的时刻,比如笔记本上的 9:12。
- Δ(目标间隔)目标时间网格的间隔,比如气象局要求的 30 分钟。
- 向下取整把 t_i 除以 Δ 后向下取整,得到它落在第几个网格区间。
- 乘回间隔把网格编号乘回 Δ,得到该区间的起点时刻,完成时间戳规整。
降采样聚合
自动站每 5 分钟吐一条数据,一个月下来积了三万多条,而气象局只要每小时一条。你不能随手删掉中间的数据——9:00 到 9:55 之间那 12 条记录,每一条都带着真实信息,你得想个办法把它们“浓缩”成一条。
把高频数据转换成低频数据的操作叫降采样(Downsampling)。它的核心思想是:以目标时间窗为单位,把窗内所有观测值通过一个聚合函数压缩成一个代表值。聚合函数怎么选,决定了你保留哪种信息。最常见的聚合是均值,它表达窗口内的“平均水平”,适合温度这类平稳变量。但如果业务关心窗口内的极值——比如服务器流量峰值、降雨瞬时强度——就该用最大值或最小值。金融行情里还有一种经典的 OHLC 聚合:同时保留窗口的开盘价、最高价、最低价和收盘价四个值。
值得注意的是,降采样必然损失信息。窗口内部的细节一旦被压成一个数,就再也找不回来。所以选择聚合函数,本质是一次信息取舍的决策:报表要回答什么问题,就选能保留那个答案的聚合方式。选错了口径,后面的分析就像拿着错版的摘要读整本书。
这就像把每分钟一行的流水总账浓缩成每小时一行的摘要,摘要用什么口径,取决于这份报表要回答什么问题。浓缩完毕,再看反方向——把稀疏记录“补密”的升采样。
- X_j(第 j 条观测)窗口内任意一条原始记录,比如 9:00 到 9:55 之间的第 j 个温度读数。
- n_i(窗口容量)第 i 个时间窗内一共有几条观测,比如 5 分钟数据聚到 1 小时,n_i 通常等于 12。
- 均值聚合把窗口内 n_i 条观测全部相加,再除以 n_i,得到窗口的平均水平。
- 最大值聚合在窗口内逐条比较,保留最大者,适合流量峰值、瞬时极值类业务。
升采样插值
翻看笔记本时你发现,9:30 之后直接跳到了 10:30——10 点整你接了个电话,忘了记录。气象局规定整点必须有值,你不能空着。于是你盯着 9:30 的 18 度和 10:30 的 21 度,心里盘算:10:00 大概介于两者之间,估个 19.5 度吧。
把低频数据转换成高频数据的操作叫升采样(Upsampling)。与降采样的“浓缩”不同,升采样做的是“补全”:目标时刻本来没有观测,只能从相邻的已知点推算一个估计值。这个推算过程就是插值(Interpolation)。最常用的线性插值假设两个已知点之间的变化是均匀的,把前后两点连成一条直线,目标时刻在直线上取对应的值。样条插值则用分段低次多项式穿过多个已知点,保证曲线处处连续平滑,适合温度、压力这类变化平缓的物理量。还有一种更偷懒的前向填充,不画线,直接把上一个有效观测值复制到缺失时刻,实现最简单,只适合变化非常缓慢的变量。
但请记住一个关键认知:插值是估计,不是实测。无论哪种方法,都不会增加真实信息量。如果真实曲线在缺失区间里剧烈波动,线性插值会把它平滑成一条直线,反而掩盖了关键的转折。升采样之后数据点变多了,模型却没有“看到”更多的真实世界。
你盯着 9:30 和 10:30 两个点,在它们之间连一条线,取中点——这就是插值的手工版。但补空之前还有一道坎:如果你的记录时间本身就不是整点,插值同样无从下手,必须先规整。这正是下一节的内容。
- X(t₀) 与 X(t₁)缺失点前后两个已知观测值,分别对应左端点和右端点的实测温度。
- t − t₀(时间距离)目标时刻距离左端点的时长,决定估计值在直线上前进多远。
- 变化速度前后温度差除以时间差,得到单位时间内的平均变化速度。
- 线性外推取值从 X(t₀) 出发,按速度推进 t − t₀,得到目标时刻的插值估计。
不规则处理
有一次你忙昏了头,记录时间变得七零八落:9:12、9:47、10:03、10:38……每个时刻都不在气象局的整点网格上。你辩解:“我量得挺勤的啊!”但报表需要的是标准网格,没人关心你的生活节奏。
现实世界中的绝大多数数据都是不规则采样(Irregular Sampling):传感器偶发掉线、日志写入抖动、人工记录随性发挥,相邻时间间隔忽长忽短。要分析这类数据,第一步不是插值,而是均匀化——把观测点对齐到固定频率的网格上。均匀化的标准做法是重索引(Reindex):先构造目标网格,再为每个网格时刻找值。网格时刻恰好有观测,直接采用;网格时刻没有观测,就按规则从邻近观测推导。
最常见的推导规则是前向填充(Forward Fill,简称 ffill):用最近一个过去时刻的有效值填充当前缺失。它适合“系统状态会持续一段时间”的变量,比如设备的运行模式、液位高度。如果想要更平滑的结果,可以再叠加插值。多源数据的对齐也是同一套思路:不同设备、不同日志的时间戳先各自规整到公共网格,才能在同一个坐标系下做联合分析。否则一台设备说 9:12,另一台说 9:13,你以为是在同一时刻,其实差了一分钟。
不规则数据就像随手记的备忘录,必须先誊写到标准表格里才能统计。到这里,概念层面的招式都讲完了——接下来看看这些操作在代码里如何落地。
- t_i(目标时刻)网格上需要填值的缺失时刻,比如 9:30。
- 候选集合所有不晚于 t_i 的观测时刻组成的集合。
- 取最近前值从候选中选出最大的 t_j,也就是离 t_i 最近的过去观测。
- 前向填充把该观测值直接复制给目标时刻,完成填充。
工程实现
手工誊了一个月的数据后,你痛定思痛,决定把整套流程写成气象站的“自动誊写程序”。在 Python 生态里,pandas 的 resample 就是这把趁手的工具,几乎所有的时序预处理都从它开始。
resample 的核心三件套是:频率规则、聚合函数、插值方式。第一步用 resample('1H') 把数据按小时分组;第二步接 agg 指定聚合函数,比如均值和最大值;第三步如果要从低频回到高频,再对结果 resample 后调用 interpolate 补点。这三个动作,正好对应前面讲的降采样、升采样与对齐。如果你拿到的是不规则数据,则用 reindex 先构造标准网格,再用 ffill 或 nearest 填充缺失。
频率规则字符串有固定语法:T 表示分钟,H 表示小时,D 表示天,前面加数字表示倍数,比如 15T 就是 15 分钟。对齐网格时,label 与 closed 参数控制窗口标签取左端点还是右端点,对应前面说的左对齐与右对齐。工程上还要心里有数:降采样会让索引变稀疏,升采样会产生大量 NaN 需要填充,聚合结果的列名会变成多层索引——这些都是新手最容易懵的地方。
誊写程序运行顺畅,但你交报表时突然意识到一个哲学问题:报表上的数字,哪些是真的、哪些是补的?于是最后一节,我们来聊聊应用场景和那些容易踩的坑。
- t_g(目标网格时间)规整后标准网格上的某个时刻,比如 9:30。
- 绝对距离每个原始观测时刻与目标时刻的时间差取绝对值。
- arg min(找最近)在所有候选 t_i 中找出使绝对距离最小的那一个。
- 取值映射把最近观测时刻对应的观测值赋给目标网格时刻。
应用与误区
报表交上去没两天,气象局打来电话:“9:45 那条记录,你是怎么知道的?”你支支吾吾——当时为了凑齐整点,你偷偷用了 10:30 的实际观测值去填 9:45。这就是典型的用未来数据填过去。
重采样与对齐在真实业务里无处不在:监控平台把秒级指标降采样成分钟级,用于流量峰值告警;智能工厂把不同传感器的数据对齐到同一时间轴,才能做多模态故障诊断;量化系统把逐笔成交数据重采样成 1 分钟 K 线,再喂给因子模型。但工程实践中藏着两个高频陷阱。第一个是信息丢失:降采样把窗口压成一个值,峰值、长尾细节全部消失,如果聚合口径和实际关注点不一致,后续模型会“看不见”关键信号。比如你想监控服务器 5 分钟内的最大延迟,却用了均值聚合——高峰期的毛刺被平均掉了,告警自然失灵。
第二个陷阱更隐蔽,叫未来数据泄漏。用缺失点之后的观测值(反向填充,bfill)填补训练数据,模型在训练时等于“偷看”了未来的答案,指标漂亮得惊人;可一旦上线做实时预测,未来还没发生,拿不到那个值,指标瞬间崩塌。因此,任何进入模型的数据,一律只能用过去信息(前向填充或插值)来补,反向填充只允许在纯离线分析的场景出现。
你默默修正了 9:45 那条记录。最后在报表扉页写下四行心得:降采样用聚合,浓缩不编造;升采样用插值,补全靠估计;不规则先对齐,建模才可靠;未来值不能碰,泄漏是大忌。
- t_next(未来最近时刻)在目标时刻 t_i 之后的最近一个观测时刻。
- 约束条件t_j ≥ t_i 保证候选全部来自“未来”,这正是泄漏的根源。
- 取最小值从未来候选中选出时间上最近的一个观测时刻。
- 反向填充把未来时刻的观测值复制到当前缺失处,完成 bfill 操作。
AI 应用场景
服务器监控指标的降采样聚合
阶段:数据预处理与特征工程
解决的问题:监控系统每秒采集数千条指标,直接存储成本高、告警容易漏掉瞬时尖峰。传统做法是随机抽样,可能恰好丢失峰值;用降采样聚合则能按业务关注点保留关键信号。
具体案例:某云厂商的 SRE 团队把每 5 秒一条的 CPU 和延迟指标,用 resample('1M').agg('max') 聚合成分钟级指标。延迟告警只看最大值,一旦分钟最大延迟超过阈值就触发报警,既降低了存储成本,又不再漏掉瞬时抖动。
智能工厂多传感器时间对齐
阶段:多源数据融合
解决的问题:振动、温度、电流三个传感器频率各不相同,时间戳错位,直接拼接会导致特征对不上真实物理时刻。传统人工对齐效率低且容易出错;用重索引把三路数据对齐到同一时间网格后,模型才能学到“同一时刻的多维状态”。
具体案例:某电机故障诊断项目中,振动传感器 1kHz、温度每 10 秒一条、电流 50Hz。团队先统一时区,再用 reindex 对齐到 10ms 网格并前向填充,构造出时序特征矩阵输入 LSTM,故障识别准确率从 78% 提升到 93%。
金融高频数据重采样成 K 线
阶段:特征构造
解决的问题:逐笔成交数据量巨大且时间间隔不均匀,无法直接输入模型;传统做法是手工挑特征,容易遗漏量价关系。用重采样把逐笔数据聚合成固定周期的 OHLC 四项,再衍生出收益率、振幅等因子,特征工程更规范、可复现。
具体案例:某量化团队把股票逐笔成交数据 resample('1T').agg({'price': 'ohlc', 'volume': 'sum'}) 生成 1 分钟 K 线,再基于 K 线计算 30 分钟动量因子,输入 LightGBM 预测次日涨跌,回测夏普比率显著优于直接使用成交明细的方案。
Python 演示
import pandas as pdimport numpy as np np.random.seed(42)base = pd.Timestamp('2024-01-01 08:00:00') # 生成 60 个不规则时间戳,间隔随机为 5-24 分钟offsets = np.cumsum(np.random.randint(5, 25, 60))times = base + pd.to_timedelta(offsets, unit='m') # 模拟温度读数:趋势正弦波动加噪声temps = 20 + 10 * np.sin(np.arange(60) / 6) + np.random.normal(0, 0.8, 60)df = pd.DataFrame({'temp': temps}, index=pd.DatetimeIndex(times, name='time'))print('irregular records:', len(df)) # 1) 降采样:每 1 小时聚合一次,同时算均值和最大值down = df.resample('1H').agg({'temp': ['mean', 'max']})print('downsampled rows:', len(down)) # 2) 升采样:从 1 小时插值回每 15 分钟up = down['temp']['mean'].resample('15T').interpolate(method='linear')print('upsampled rows:', len(up), 'first:', round(float(up.iloc[0]), 2)) # 3) 不规则数据对齐:重索引到 30 分钟标准网格,前向填充grid = pd.date_range('2024-01-01 08:00', '2024-01-01 14:00', freq='30T')aligned = df['temp'].reindex(grid).ffill()print('aligned grid points:', len(aligned))print(aligned.head(4).to_string())
resample 做降采样聚合、用 interpolate 做升采样插值、用 reindex + ffill 做不规则数据对齐。offsets = np.cumsum(np.random.randint(5, 25, 60))生成 60 个不相等的间隔,模拟“随性记录”导致的不规则采样。df = pd.DataFrame({'temp': temps}, index=pd.DatetimeIndex(times, name='time'))以不规则时间戳为索引建表,对应笔记本上记的原始温度。down = df.resample('1H').agg({'temp': ['mean', 'max']})按 1 小时分组,同时计算均值和最大值,一步完成降采样。up = down['temp']['mean'].resample('15T').interpolate(method='linear')从 1 小时升采样到 15 分钟,用线性插值补出中间时刻的估计值。aligned = df['temp'].reindex(grid).ffill()先重索引到 30 分钟标准网格,再用前向填充补缺,完成时间对齐。
常见误区
误区降采样就是把窗口内所有数据求个平均,均值最通用,反正数据都差不多,用哪个都一样。
正解均值只代表“平均水平”,会抹平峰值、谷值和分布形态。业务关注流量峰值时该用 max,关注总量时该用 sum,关注报价时该用 OHLC 四值。选错聚合函数,后续模型看到的信号就是错的——像报表摘要口径写错,整份报告都会误导人。
为何常见:均值概念最简单,多数入门教程只演示 mean,很容易让人形成“唯一答案”的错觉。
误区数据太少了就升采样,插值后数据点变多,模型训练效果一定会更好。
正解插值是估计而非实测,信息量并没有增加。线性插值假设均匀变化,若真实曲线在缺失区间剧烈波动,插值会平滑掉关键转折。更危险的是,插值点会放大模型的自信,让人误以为模型看到了更密的数据。想要更多真实数据,只能靠加强采集,而不是靠插值。
为何常见:视觉上数据点确实变多了,指标也可能因样本量上升而改善,容易产生“数据变好”的错觉。
误区LSTM 不是能处理序列吗?时间戳不规则也没关系,直接把原始数据按时间顺序输入就行。
正解绝大多数序列模型假设输入是等间隔的,时间信息蕴含在“位置”里,而不是时间戳的数值里。不规则间隔会让模型错误理解节奏——把 1 分钟间隔和 1 小时间隔当成同样的一步。必须先重采样或对齐到固定频率;如果确实想保留间隔信息,需要额外设计时间间隔特征,但预处理仍然不可省。
为何常见:序列模型的输入输出格式看起来统一,容易忽略它背后“等间隔”的强假设。
误区缺了 10:00 的记录,用 10:30 的实际观测值补上,总比插值估计的准吧?
正解用未来值(bfill)填补训练数据属于未来数据泄漏:模型在训练时通过“偷看”学会了依赖未来信号,而线上预测那一刻未来还没发生,指标会瞬间崩塌。离线画图可以这样补,但任何进入模型的数据,一律只能用过去信息(前向填充或插值)。
为何常见:离线数据都是“已经发生”的,后一个值就在手边,看起来更真实,容易忽略时间因果顺序。
面试题
Q1. 降采样的本质是什么?
- A.把数据频率提高
- B.高频数据聚合为低频← 正确答案
- C.直接删除全部数据
- D.随机抽样部分数据
答案:B。降采样是从高频往低频转换,把窗口内多个观测值通过聚合函数压缩成一个代表值,故选 B。A 是升采样,C 和 D 都不属于有信息保留的规整操作。
Q2. 以下哪个是升采样的常用手段?
- A.对窗口取平均值
- B.线性插值补中间← 正确答案
- C.对窗口取最大值
- D.直接丢弃缺失值
答案:B。升采样是从低频往高频补点,线性插值是补出中间时刻估计值的经典方法,故选 B。取均值和取最大值是降采样的聚合手段,丢弃缺失值不产生新数据。
Q3. 5 分钟数据降采样到 1 小时,想保留“每小时峰值”,应选哪种聚合?
- A.窗口内求平均值
- B.窗口内求最大值← 正确答案
- C.取窗口首个观测
- D.窗口内求和汇总
答案:B。峰值对应窗口内的最大观测值,用 max 聚合才能保留瞬时极值。均值抹平峰值,首值只看开头,求和代表总量,都不适合峰值告警类场景。
Q4. 时间对齐中“前向填充”的含义是什么?
- A.用前一个有效值填充← 正确答案
- B.用后一个有效值填充
- C.用窗口均值填充
- D.直接删除缺失行
答案:A。前向填充(ffill)用最近一个过去时刻的有效值填充当前缺失,故选 A。用后一个值填充是反向填充 bfill,可能引入未来数据泄漏。
Q5. 关于升采样插值,下列说法正确的有?
- A.插值并不增加真实信息← 正确答案
- B.线性插值假设均匀变化← 正确答案
- C.样条插值曲线更平滑← 正确答案
- D.插值结果一定准确无误
答案:ABC。插值是估计而非实测,不增加真实信息,A 正确;线性插值确实假设两点间均匀变化,B 正确;样条插值用分段多项式拟合,曲线更平滑,C 正确;插值在剧烈波动区间可能严重失真,D 错误。
Q6. 为什么建模前必须把不规则采样数据对齐到固定频率?
- A.让图表看起来更整齐美观
- B.多数模型要求等间隔输入← 正确答案
- C.减少数据存储的开销
- D.方便用未来值填补缺失
答案:B。序列模型(如 LSTM)假设输入等间隔,时间信息藏在位置里,不规则间隔会让模型误解节奏,故选 B。对齐主要服务模型假设,而非美观或存储;对齐更不能成为用未来值的理由。
Q7. 下列哪个业务最适合用“最大值”聚合做降采样?
- A.天气平均气温周报
- B.服务器流量峰值告警← 正确答案
- C.股票每日收盘价格
- D.用户每日步数统计
答案:B。峰值告警关心窗口内是否出现极端值,必须用 max 保留瞬时尖峰,故选 B。平均气温适合均值,收盘价适合末值,步数通常用总和。
Q8. 关于用未来值填补缺失(反向填充),说法正确的有?
- A.会造成未来数据泄漏← 正确答案
- B.训练好但线上预测失真← 正确答案
- C.只适合事后离线分析← 正确答案
- D.可用于实时在线预测
答案:ABC。反向填充把未来观测复制到过去,会泄漏未来信息,A 正确;训练时偷看未来导致评估虚高,上线时拿不到未来值,B 正确;它只适合整理历史图表等离线场景,C 正确;实时预测禁止使用,D 错误。
Q9. 线性插值估计 t 时刻的值,主要依赖哪些观测?
- A.只依赖前一个观测点
- B.只依赖后一个观测点
- C.依赖前后两个相邻点← 正确答案
- D.依赖所有历史观测点
答案:C。线性插值公式用缺失点前后两个相邻观测连直线,在目标时刻取线上的值,故选 C。它不依赖全部历史,也不只用单侧数据。
Q10. 一段时间间隔杂乱的时间序列要输入 LSTM,正确的第一步预处理是?
- A.直接输入原始时间戳
- B.重采样并固定频率对齐← 正确答案
- C.删除所有非整点记录
- D.只按时间排序即可用
答案:B。LSTM 假设等间隔输入,杂乱间隔必须先重采样到固定频率并做时间对齐,故选 B。直接输入时间戳或仅排序都无法满足等间隔假设,删数据则会造成大量信息浪费。