自学教程 学编程从这里开始

Pandas 时间序列分析

承接前面窗口、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 时序四大基础类型

  1. datetime64[ns]:时间点(最常用,订单时间、交易时间)
  2. timedelta64[ns]:时间间隔(时间差,支付耗时)
  3. Period:周期(年月、季度,适合按月汇总)
  4. 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)

十四、高频坑清单

  1. 时间索引没有排序,resample、rolling 结果全部错误
  2. 混淆 rolling(滑动重叠窗口)和 resample(切块不重叠)
  3. 带时区、不带时区时间混用,运算报错
  4. shift 后产生的NaN没有处理,直接参与计算
  5. 大量缺失时序数据直接drop,破坏时间连续性,优先插值/ffill
  6. dt.date 返回Python date对象,不要用于大小比较,直接用datetime索引比较
  7. resample 上采样默认会产生大量NaN,需要手动填充

十五、时序工具选型速查表

需求工具
按天/周/月汇总resample
N日移动平均、滚动指标rolling
累计统计、累计最大值expanding
近值权重更高,平滑降噪ewm
获取昨日、上周同期数据shift
计算增量、变化量diff
提取年月、星期、小时dt 访问器
时间间隙补全asfreq + ffill/interpolate
标签:

0 条笔记