承接前面窗口、dt、shift、resample 等章节,本篇为时间序列综合主线教程,整合时间索引构建、时间解析、重采样、移位差分、窗口统计、时间区间、时区、缺失时序填充、时序绘图,是订单、销售、行情、传感器时序分析的完整体系,保持系列教程统一风格。
前置导入与示例数据
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 构造时序示例:连续15天销售数据
df = pd.DataFrame({
"sales": [120, 90, 150, 130, 180, 160, 200, 170, 140, 190, 210, 165, 175, 220, 185],
"promo": [0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0]
})
# 生成时间索引
df["date"] = pd.date_range(start="2025-01-01", periods=15, freq="D")
df = df.set_index("date")
print(df)
一、时序核心类型回顾
Pandas 时序四大基础类型
datetime64[ns]:时间点(最常用,订单时间、交易时间)timedelta64[ns]:时间间隔(时间差,支付耗时)Period:周期(年月、季度,适合按月汇总)DatetimeIndex:时间索引,时序分析的前提,rolling/resample 都依赖有序时间索引
重点:做时序分析,优先把时间字段设为索引,并且必须排序
df = df.sort_index()
二、时间字符串解析 pd.to_datetime
# 基础转换,无法解析自动转为NaT
df["order_time"] = pd.to_datetime(df["order_time"], errors="coerce")
# 指定格式,速度更快
pd.to_datetime(df["order_time"], format="%Y-%m-%d %H:%M:%S", errors="coerce")
NaT:时间类型缺失值,判断空值依旧使用isna()dayfirst=True:适配 日/月/年 格式
三、DatetimeIndex 快速构造
# 生成连续日期
pd.date_range(start="2025-01-01", end="2025-01-10", freq="D")
# 从指定日期开始,生成10个小时
pd.date_range(start="2025-01-01 08:00", periods=10, freq="H")
常用 freq 频率标识
D天,H小时,T分钟,S秒B工作日,W周,M月末,MS月初,Q季度,QS季初
四、dt 访问器:提取时间分量
df["year"] = df.index.year
df["month"] = df.index.month
df["day"] = df.index.day
df["hour"] = df.index.hour
df["weekday"] = df.index.dayofweek # 0=周日,1=周一
df["is_weekend"] = df.index.dayofweek.isin([5,6])
适合按小时、星期、月份做分组统计。
五、时间筛选(切片查询)
时间索引支持自然字符串切片,非常方便
# 取2025-01-03 ~ 2025-01-08
df["2025-01-03":"2025-01-08"]
# 筛选1月全部数据
df["2025-01"]
# 筛选每天8点~18点(非索引,用dt)
df.loc[(df["order_time"].dt.hour >=8) & (df["order_time"].dt.hour <=18)]
六、resample 重采样(时序分组聚合)
resample 是时序专属 groupby,不重叠切块,和 rolling 滑动窗口区分开
# 按周汇总求和
df_weekly = df.resample("W")["sales"].sum()
# 按月均值
df_monthly = df.resample("M")["sales"].mean()
# 上采样:填充低频数据到高频(补行)
df.resample("6H").asfreq()
重采样填充方式:
df.resample("6H").ffill() # 前向填充
df.resample("6H").bfill() # 后向填充
七、shift 移位 + diff 差分
时序特征工程高频组合
# 向后移位1行:昨日销售额
df["sales_last1"] = df["sales"].shift(1)
# 向前移位1行:下一日销售额
df["sales_next1"] = df["sales"].shift(-1)
# 一阶差分:当日相比昨日增量
df["sales_diff"] = df["sales"].diff(1)
# 同比:shift(7) 周同比(日数据)
df["sales_week_last"] = df["sales"].shift(7)
差分常用于平稳性检验、收益率计算。
八、窗口统计(rolling / expanding / ewm)
时序平滑、滚动指标,前面独立章节已经细讲,这里汇总使用范式
# 3日滚动均值
df["ma3"] = df["sales"].rolling(window=3, min_periods=1).mean()
# 累计均值
df["exp_mean"] = df["sales"].expanding().mean()
# EWMA指数平滑
df["ewm5"] = df["sales"].ewm(span=5, adjust=False).mean()
九、时区处理
# 无时区时间本地化,绑定上海时区
df_tz = df.tz_localize("Asia/Shanghai")
# 时区转换
df_utc = df_tz.tz_convert("UTC")
# 移除时区
df_local = df_tz.tz_localize(None)
⚠️ 带时区和不带时区的时间不能直接比较、相减。
十、时序缺失值填充
时序数据不能简单直接drop,优先时序填充
# 前向填充(延续上一个有效值,适合库存、行情)
df["sales_ffill"] = df["sales"].ffill()
# 线性插值(适合连续传感器、平滑指标)
df["sales_interp"] = df["sales"].interpolate(method="linear")
十一、Period 周期类型
把时间转为周期,适合年月、季度分组
df["month_period"] = df.index.to_period("M")
df.groupby("month_period")["sales"].sum()
十二、时序可视化
df[["sales","ma3"]].plot(figsize=(10,4))
plt.title("销售时序与3日移动平均")
plt.show()
十三、业务完整时序分析流水线
def time_series_pipeline(df_raw, time_col, val_col):
# 1. 时间解析
df_raw[time_col] = pd.to_datetime(df_raw[time_col], errors="coerce")
# 2. 去空、排序、设索引
df_raw = df_raw.dropna(subset=[time_col])
df_raw = df_raw.set_index(time_col).sort_index()
# 3. 衍生特征
df_raw["weekday"] = df_raw.index.dayofweek
df_raw["hour"] = df_raw.index.hour
df_raw["lag1"] = df_raw[val_col].shift(1)
df_raw["diff1"] = df_raw[val_col].diff(1)
# 4. 窗口指标
df_raw["ma3"] = df_raw[val_col].rolling(3, min_periods=1).mean()
df_raw["ewm5"] = df_raw[val_col].ewm(span=5, adjust=False).mean()
return df_raw
df_result = time_series_pipeline(df.reset_index(), "date", "sales")
print(df_result)
十四、高频坑清单
- 时间索引没有排序,resample、rolling 结果全部错误
- 混淆 rolling(滑动重叠窗口)和 resample(切块不重叠)
- 带时区、不带时区时间混用,运算报错
- shift 后产生的NaN没有处理,直接参与计算
- 大量缺失时序数据直接drop,破坏时间连续性,优先插值/ffill
- dt.date 返回Python date对象,不要用于大小比较,直接用datetime索引比较
- resample 上采样默认会产生大量NaN,需要手动填充
十五、时序工具选型速查表
| 需求 | 工具 |
|---|---|
| 按天/周/月汇总 | resample |
| N日移动平均、滚动指标 | rolling |
| 累计统计、累计最大值 | expanding |
| 近值权重更高,平滑降噪 | ewm |
| 获取昨日、上周同期数据 | shift |
| 计算增量、变化量 | diff |
| 提取年月、星期、小时 | dt 访问器 |
| 时间间隙补全 | asfreq + ffill/interpolate |
0 条笔记