时间序列
学习目标
- 掌握日期时间类型的创建和转换
- 学会时间序列的索引与切片
- 掌握重采样(resample)和频率转换
- 学会滚动窗口计算(rolling)
为什么需要时间序列?
很多数据都和时间相关——股票价格、销售数据、网站访问量、天气记录……处理时间数据是数据分析的必备技能。
日期时间类型
创建时间戳
import pandas as pd
import numpy as np
# 创建单个时间戳
ts = pd.Timestamp("2024-01-15")
print(ts) # 2024-01-15 00:00:00
print(ts.year) # 2024
print(ts.month) # 1
print(ts.day) # 15
print(ts.day_name()) # Monday
# 更多格式
ts2 = pd.Timestamp("2024-01-15 14:30:00")
ts3 = pd.Timestamp(year=2024, month=3, day=20)
字符串转日期
# 单列转换
dates = pd.Series(["2024-01-15", "2024-02-20", "2024-03-10"])
dt_series = pd.to_datetime(dates)
print(dt_series)
print(dt_series.dtype) # datetime64[ns]
# 处理不同格式
pd.to_datetime("15/01/2024", format="%d/%m/%Y")
pd.to_datetime("2024年3月15日", format="%Y年%m月%d日")
# 处理无法解析的值
dirty = pd.Series(["2024-01-15", "not a date", "2024-03-10"])
clean = pd.to_datetime(dirty, errors="coerce") # 无法解析的变成 NaT
print(clean)
# 0 2024-01-15
# 1 NaT ← Not a Time
# 2 2024-03-10
日期范围
# 创建日期范围
dates = pd.date_range("2024-01-01", periods=10, freq="D") # 每天
print(dates)
# 不同频率
pd.date_range("2024-01-01", periods=12, freq="ME") # 每月末
pd.date_range("2024-01-01", periods=4, freq="QE") # 每季度末
pd.date_range("2024-01-01", "2024-12-31", freq="W") # 每周
# 常用频率代码
# D=天, W=周, ME=月末, MS=月初, QE=季末, YE=年末
# h=小时, min=分钟, s=秒
# B=工作日
时间序列数据
创建时间序列 DataFrame
# 模拟 2024 年每天的销售数据
np.random.seed(42)
dates = pd.date_range("2024-01-01", periods=365, freq="D")
sales = pd.DataFrame({
"日期": dates,
"销售额": np.random.randint(5000, 20000, 365) + \
np.sin(np.arange(365) * 2 * np.pi / 365) * 3000 # 加入季节性
})
sales = sales.set_index("日期")
print(sales.head())
print(sales.shape) # (365, 1)
提取日期组件
df = pd.DataFrame({
"日期": pd.date_range("2024-01-01", periods=100, freq="D"),
"销量": np.random.randint(10, 100, 100)
})
# 用 dt 访问器提取日期组件
df["年"] = df["日期"].dt.year
df["月"] = df["日期"].dt.month
df["日"] = df["日期"].dt.day
df["星期几"] = df["日期"].dt.day_name()
df["是否周末"] = df["日期"].dt.dayofweek >= 5 # 5=周六, 6=周日
df["第几周"] = df["日期"].dt.isocalendar().week
print(df.head())
时间索引切片
当日期是索引时,可以用字符串方便地切片:
# sales 的索引是日期
# 选取 2024 年 3 月的数据
print(sales.loc["2024-03"])
# 选取 2024 年第一季度
print(sales.loc["2024-01":"2024-03"])
# 选取某一天
print(sales.loc["2024-06-15"])
重采样(resample)
重采样是时间序列最核心的操作——改变数据的时间频率。
降采样(高频 → 低频)
# 每日数据 → 每月数据
monthly = sales.resample("ME").sum() # 月末汇总
print(monthly.head())
# 每日 → 每周
weekly = sales.resample("W").mean() # 周平均
# 每日 → 每季度
quarterly = sales.resample("QE").agg({
"销售额": ["sum", "mean", "max"]
})
print(quarterly)
升采样(低频 → 高频)
# 月度数据 → 每日数据(需要填充)
daily = monthly.resample("D").ffill() # 前向填充
# 或
daily = monthly.resample("D").interpolate() # 插值