7.数据的预测分析及可视化
7. 数据的预测分析及可视化
文章目录
- 7. 数据的预测分析及可视化
- 7. 数据的预测分析及可视化
- 7.1 动态数列的基本分析
- 7.1.1 动态数列的介绍
- 7.1.1.1 动态数列的概念
- 7.1.1.2 动态数列的构建
- 7.1.2 动态数列的分析维度
- 7.1.2.1 绝对动态数列(水平分析)
- 7.1.2.2 相对动态数列(速度分析)
- 7.1.2.3 平均动态数列(趋势分析)
- 7.2 动态数列预测分析
- 7.2.1 趋势预测模型构建
- 7.2.1.1 模型选择决策树
- 7.2.1.3 线性模型建模全流程
- 7.2.2 平滑预测方法对比
- 7.2.2.1 移动平均家族
- 7.2.2.2 指数平滑进阶
- 7.3 时间序列数据的可视化分析
- 7.3.1 股票数据可视化最佳实践
- 7.3.1.1 多维度数据探索
- 7.3.1.2 K线图实战应用
- 7.3.2 收益率分析深度解读
- 7.3.2.1 风险指标计算
- 7.3.2.2 季节效应分析
- 总结与工程化建议
- 7.4.1 核心技术图谱
- 7.4.2 生产环境实践要点
7. 数据的预测分析及可视化
在数据科学领域,预测分析与可视化是揭示数据动态规律、辅助决策的核心技术。本章围绕时间序列数据展开,结合Python代码演示动态数列的分析方法、预测模型构建及金融数据可视化,适合数据分析从业者、金融分析师及相关领域学习者参考。通过融入实际业务场景解析与模型选择逻辑,帮助读者建立完整的时间序列分析思维体系。
7.1 动态数列的基本分析
7.1.1 动态数列的介绍
7.1.1.1 动态数列的概念
动态数列(时间序列)是将同一统计指标在不同时间点的数值按时间顺序排列形成的序列,由时间维度和指标数值两部分构成。例如:
- 宏观经济领域:GDP年度数据、CPI月度数据
- 金融市场:股票日收盘价、债券收益率曲线
- 商业分析:电商平台月活跃用户数、门店周销售额
其核心价值在于通过时序数据的纵向对比,揭示现象的长期趋势(T)、季节波动(S)、**周期循环(C)和随机波动(I)**四大构成要素,为业务预测提供底层数据支撑。例如通过分析某品牌手机过去三年的季度销量数据,可识别春节促销带来的季节效应与技术迭代引发的周期波动。
7.1.1.2 动态数列的构建
- 时间序列数据预处理
使用Pandas读取结构化数据时,需特别注意时间索引的规范性:
import pandas as pd
# 配置数据展示格式(仅显示核心信息,避免输出冗余)
pd.set_option('display.precision', 4) # 数值精度控制
pd.set_option('display.max_rows', 10) # 限制表格展示行数
# 读取多表单数据,构建时间序列对象
YQdata = pd.read_excel('DaPy_data.xlsx', 'YQdata', index_col=0, parse_dates=True)
QTdata = pd.read_excel('DaPy_data.xlsx', 'QTdata', index_col=0, parse_dates=True)
- 通过
index_col=0
指定时间列作为索引,确保生成DatetimeIndex
类型 - 建议使用
pd.to_datetime()
显式转换时间格式,处理非标准时间字符串 - 通过
sort_index()
保证时间顺序的正确性
- 基础可视化验证
绘制季度数据趋势图时,建议添加基础标注增强可读性:
ax = QTdata.plot(figsize=(10, 4), grid=True, title="季度数据趋势分析", ylabel="指标值")
ax.xaxis.set_major_locator(plt.MaxNLocator(5)) # 控制x轴标签密度
plt.show()
图示价值:快速识别数据是否存在明显的上升 / 下降趋势、异常波动点或周期性模式(如零售数据的Q4峰值)。
- 年度数据聚合实践
从季度数据构建年度序列时,需注意业务逻辑对聚合方式的影响:
# 从时间索引中提取年份(处理格式为'YYYY-Q'的季度索引)
QTdata['Year'] = QTdata.index.str[:4]
# 按年份聚合GDP数据(业务场景:计算各年经济总量)
YGDP = QTdata.groupby('Year')['GDP'].sum().sort_index()
- 总量指标(如GDP、销售额)通常使用求和聚合
- 平均指标(如用户留存率、利润率)需使用加权平均
- 极值指标(如最高股价、最低气温)应提取最值
7.1.2 动态数列的分析维度
动态数列分析体系通过多维度指标矩阵,实现对数据动态特征的立体刻画:
7.1.2.1 绝对动态数列(水平分析)
- 定基增长量核心逻辑:以固定基期(通常为业务起始期)为参照,衡量各期相对于初始状态的绝对变化量
应用场景:
# 构建动态数列数据框(保留原始数据便于对比)
YGDPds = pd.DataFrame(YGDP, columns=['原始值'])
# 定基增长量 = 报告期值 - 基期值(基期为时间序列第一个数据点)
YGDPds['定基增长量'] = YGDPds['原始值'] - YGDPds['原始值'].iloc[0]
- 企业分析:计算各年营收相对于创业初期的累计增长额
- 科研领域:测量实验数据相对于基准值的绝对偏移量
- 环比增长量核心逻辑:反映相邻两期的实际变化幅度,捕捉短期波动
注意事项:
# 环比增长量 = 报告期值 - 前一期值(shift(1)实现数据滞后一阶)
YGDPds['环比增长量'] = YGDPds['原始值'].diff(1)
- 适用于短期趋势分析,对季节性数据需结合周期调整
- 当数据存在异常值时,建议使用移动平均后的序列计算
7.1.2.2 相对动态数列(速度分析)
- 定基发展速度经济意义:反映长期发展总趋势,常用于规划完成度评估
公式变形: 定基发展速度 = ∏ i = 1 n 环比发展速度 \text{定基发展速度} = \prod_{i=1}^{n} \text{环比发展速度} 定基发展速度=∏i=1n环比发展速度
# 定基比 = 报告期值 / 基期值(百分比形式需后续乘以100)
YGDPds['定基发展速度'] = YGDPds['原始值'] / YGDPds['原始值'].iloc[0]
- 环比发展速度市场应用:
# 环比比 = 报告期值 / 前一期值(shift(1)获取前一期数据)
YGDPds['环比发展速度'] = YGDPds['原始值'] / YGDPds['原始值'].shift(1)
- 股票分析:计算每日股价相对于前一日的涨幅
- 零售行业:监测月度销售额环比增长率,识别促销活动效果
7.1.2.3 平均动态数列(趋势分析)
- 几何平均法的适用条件
当现象呈现连续性增长(如复利计算、技术迭代指数)时,几何平均法能更准确反映平均发展水平,避免算术平均对极端值的敏感性。
# 计算时间序列长度(需排除基期数据影响)
n = len(YGDPds) - 1
# 几何平均公式:(末期值/初期值)^(1/时间间隔)
average_growth_rate = (YGDPds['原始值'].iloc[-1] / YGDPds['原始值'].iloc[0]) ** (1/n)
print(f"平均发展速度:{average_growth_rate:.3%}") # 输出百分比格式
7.2 动态数列预测分析
7.2.1 趋势预测模型构建
7.2.1.1 模型选择决策树
- 线性模型(一次趋势模型)假设条件:数据呈现稳定的线性增长,无明显加速 / 减速迹象
代码增强:添加模型诊断步骤,检查残差是否符合正态分布
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# 生成模拟数据(斜率=2,截距=1)
x = np.arange(1, 21) # 时间序列(1-20期)
y_linear = 1 + 2 * x + np.random.normal(0, 5, 20) # 加入随机扰动
# 最小二乘法拟合
slope, intercept, r_value, p_value, std_err = stats.linregress(x, y_linear)
plt.scatter(x, y_linear, label='原始数据')
plt.plot(x, intercept + slope*x, 'r-', label=f'拟合线: y={slope:.2f}x + {intercept:.2f}')
- 非线性模型对比
在同一坐标系绘制不同模型曲线,直观展示适用场景差异:
# 对数模型:适用于初期快速变化,后期趋于稳定的场景(如用户活跃度)
y_log = 1 + 0.2 * np.log(x)
# 指数模型:适用于持续加速增长场景(如病毒传播、技术扩散)
y_exp = 0.2 * np.exp(0.1 * x)
# 幂函数模型:适用于存在基数效应的增长(如电商GMV)
y_pow = 0.2 * x**0.5
plt.figure(figsize=(12, 6))
plt.plot(x, y_linear, 'o-', label='线性模型')
plt.plot(x, y_log, 's-', label='对数模型')
plt.plot(x, y_exp, 'd-', label='指数模型')
plt.legend()
7.2.1.3 线性模型建模全流程
- 数据标准化处理
当时间索引为年份(如2010-2023)时,建议转换为相对时间(1-14),避免数值过大影响模型收敛:
import statsmodels.api as sm
# 因变量:年度GDP数据(需确保为平稳序列或通过差分处理)
Yt = YGDP
# 自变量:相对时间序列(从1开始,避免0值影响截距项)
Xt = np.arange(1, len(Yt)+1)
- 模型诊断与优化
# 添加常数项(截距项)
Xt = sm.add_constant(Xt)
# 普通最小二乘法回归
model = sm.OLS(Yt, Xt).fit()
# 关键指标解读:
# - R-squared:模型解释力(越接近1越好)
# - Prob(F-statistic):整体模型显著性
# - coef:回归系数(b为趋势斜率,反映每期平均变化量)
print(model.summary())
- 非线性模型转换技巧
当指数模型拟合效果更好时,可通过对数变换转化为线性问题:
# 对因变量取自然对数(假设y=ae^(bx),则ln(y)=ln(a)+bx)
Yt_log = np.log(Yt)
model_log = sm.OLS(Yt_log, Xt).fit()
# 还原预测值:exp(ln(a)+bx) = a*exp(bx)
Yt_pred = np.exp(model_log.predict(Xt))
7.2.2 平滑预测方法对比
7.2.2.1 移动平均家族
方法 | 公式 | 适用场景 | 参数意义 |
---|---|---|---|
简单平均法 | y ˉ t = 1 n ∑ i = t − n + 1 t y i \bar{y}t = \frac{1}{n}\sum{i=t-n+1}^{t} y_i yˉt=n1∑i=t−n+1tyi | 平稳无趋势序列 | n:窗口大小 |
简单移动平均 | 同上 | 短期趋势识别 | 窗口越大,平滑效果越强 |
加权移动平均 | y ˉ t = ∑ i = 0 n − 1 w i y t − i \bar{y}_t = \sum_{i=0}^{n-1} w_i y_{t-i} yˉt=i=0∑n−1wiyt−i | 重视近期数据的场景 | w i w_i wi:权重系数 |
# 季度GDP数据平滑处理
Qt = QTdata['GDP']
QtM = pd.DataFrame({'原始数据': Qt})
# 3期移动平均(反映短期波动)
QtM['M3'] = Qt.rolling(window=3, min_periods=1).mean()
# 5期移动平均(凸显长期趋势)
QtM['M5'] = Qt.rolling(window=5, min_periods=3).mean()
7.2.2.2 指数平滑进阶
双参数Holt模型(适用于有趋势的序列):
from statsmodels.tsa.holtwinters import SimpleExpSmoothing
# 初始化模型(设置初始水平和趋势参数)
model_holt = SimpleExpSmoothing(Qt, initialization_method='estimated')
# 拟合模型(设置平滑系数α和趋势系数β)
fit_holt = model_holt.fit(smoothing_level=0.3, smoothing_trend=0.1)
# 生成未来3期预测
forecast_holt = fit_holt.forecast(3)
7.3 时间序列数据的可视化分析
7.3.1 股票数据可视化最佳实践
7.3.1.1 多维度数据探索
- 数据清洗关键步骤
# 读取股票数据(包含Open/High/Low/Close/Volume/Adjusted六列)
stock = pd.read_excel('DaPy_data.xlsx', 'Stock', index_col=0, parse_dates=True)
# 处理缺失值:向前填充(适用于短期停牌数据)
stock = stock.ffill().bfill()
# 数据标准化:计算对数收益率(降低异方差影响)
stock['Log_Return'] = np.log(stock['Close']).diff()
- 复合图表绘制技巧
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=(12, 7))
# 上子图:收盘价与移动平均线
ax1.plot(stock['Close'], label='收盘价')
ax1.plot(stock['MA5'], label='5日MA')
ax1.set_title('股价趋势与技术指标')
ax1.legend()
# 下子图:成交量直方图(带正态分布拟合)
stock['Volume'].plot(kind='hist', ax=ax2, density=True, bins=20, alpha=0.6)
x = np.linspace(stock['Volume'].min(), stock['Volume'].max(), 100)
ax2.plot(x, stats.norm.pdf(x, stock['Volume'].mean(), stock['Volume'].std()), 'r-')
7.3.1.2 K线图实战应用
- 技术指标叠加
import mplfinance as mpf
# 提取特定时间段数据(包含成交量)
OHLCV = stock.loc['2023-01':'2023-03', ['Open', 'High', 'Low', 'Close', 'Volume']]
# 定义技术指标:30日移动平均线 + 布林带
add_plot = [ mpf.make_addplot(OHLCV['MA30'], panel=0, color='blue'), # 主图叠加 mpf.make_addplot(OHLCV[['Bollinger_upper', 'Bollinger_lower']], panel=0, linestyle='--')
]
# 绘制带成交量的K线图
mpf.plot(OHLCV, type='candle', volume=True, addplot=add_plot, title='2023Q1股票走势', show_nontrading=False)
- 事件标记技巧
# 定义关键事件(如财报发布日、分红日)
events = pd.to_datetime(['2023-01-15', '2023-02-27'])
# 在K线图上标记事件点
mpf.plot(OHLCV, type='candle', markersize=7, markeredgecolor='red', markevery=events, style='charles', title='重要事件影响分析')
7.3.2 收益率分析深度解读
7.3.2.1 风险指标计算
# 计算日收益率(对数收益率更符合正态分布假设)
stock['Log_Return'] = np.log(stock['Close']).diff()
# 关键风险指标:
volatility = stock['Log_Return'].std() * np.sqrt(252) # 年化波动率(假设252个交易日)
sharpe_ratio = (stock['Log_Return'].mean() / volatility) * np.sqrt(252) # 夏普比率(无风险利率设为0)
7.3.2.2 季节效应分析
# 提取月度收益率数据(转换为年-月索引)
stock['Month'] = stock.index.month
monthly_returns = stock.groupby(['Year', 'Month'])['Log_Return'].mean().unstack()
# 热力图可视化季节效应
plt.figure(figsize=(10, 6))
sns.heatmap(monthly_returns, cmap='coolwarm', annot=True, fmt='.4f')
plt.title('月度收益率热力图(2015-2023)')
plt.xlabel('月份')
plt.ylabel('年份')
总结与工程化建议
7.4.1 核心技术图谱
7.4.2 生产环境实践要点
- 数据管道:
- 使用
pandas-profiling
生成数据质量报告 - 建立时间序列数据校验规则(如时间连续性检查、异常值检测)
- 使用
- 模型部署:
- 对于实时预测场景,优先选择计算效率高的指数平滑模型
- 定期进行模型再训练(如每月更新一次趋势模型参数