【Python数据分析筑基】第九讲:时间序列分析入门——用Pandas解锁时间维度的数据洞察(万字长文+实战)
【Python数据分析筑基】第九讲时间序列分析入门——用Pandas解锁时间维度的数据洞察万字长文实战摘要本文是《Python数据分析根据方向打牢Python基础10讲》系列的第九篇。在前八讲分别夯实了通用Python、NumPy、Pandas基础、数据可视化、Scikit-learn机器学习、SQL数据库查询、Web Scraping网络爬虫和GeoPandas地理空间分析能力后我们将聚焦于数据的第四维度——时间。本讲将系统性地学习时间序列分析Time Series Analysis深度挖掘Pandas库中为时间序列量身打造的强大功能。我们将学习如何处理日期和时间、重采样、滚动窗口计算并掌握经典的时间序列分解方法如STL分解最后构建一个简单的预测模型。关键词Python, 数据分析, 时间序列分析, Pandas, 时间序列预测, 趋势分解, 重采样引言当数据随时间流动——时间序列分析的价值至此我们已经掌握了处理静态横截面数据如用户画像和空间数据如地理位置的全面技能。然而在现实世界中绝大多数有价值的数据都是动态变化的股票市场的每分钟价格零售店的每日销售额工厂传感器的每秒读数网站的每小时访问量这类按时间顺序排列的数据被称为时间序列Time Series。对它们进行分析能够帮助我们理解过去识别数据中的长期趋势、季节性模式和周期性波动。监控现在实时检测异常值或突变点如服务器故障、销售骤降。预测未来基于历史模式对未来进行合理的推断如需求预测、风险评估。在Python生态中Pandas是处理时间序列数据的绝对核心。它提供了一套极其优雅和高效的API让复杂的时间操作变得简单直观。特别说明本讲将遵循2026年的最佳实践强调时间序列的平稳性、避免未来信息泄露Look-ahead Bias等关键原则并通过真实数据集进行实战演练。本讲学习目标完成本讲的学习后你将能够熟练处理日期和时间数据包括创建DatetimeIndex、解析各种日期格式、处理时区。掌握时间序列的核心操作如选择、切片、重采样Resampling和滚动窗口Rolling Window计算。应用时间序列分解技术如STL分解将原始序列拆解为趋势、季节性和残差成分。识别和处理时间序列中的缺失值与异常值。构建并评估一个简单的基准预测模型如移动平均、朴素预测为后续更复杂的建模打下基础。第一章时间序列基石——Pandas中的日期与时间一切始于正确地表示和处理时间。1.1Timestamp与DatetimeIndexPandas提供了两种核心的时间数据结构pd.Timestamp代表一个单一的时间点类似于Python标准库中的datetime.datetime但功能更强大。pd.DatetimeIndex一个由Timestamp对象组成的索引是时间序列DataFrame的“骨架”。importpandasaspdimportnumpyasnp# 创建单个时间戳tspd.Timestamp(2026-04-03 14:30:00)print(ts)# 2026-04-03 14:30:00# 创建一个日期范围 (DatetimeIndex)date_rngpd.date_range(start2026-01-01,end2026-12-31,freqD)# D代表天print(date_rng[:5])# DatetimeIndex([2026-01-01, 2026-01-02, ..., 2026-01-05], dtypedatetime64[ns], freqD)1.2 将普通DataFrame转换为时间序列通常你的数据会有一个包含日期的列。我们需要将其转换为索引。# 模拟一个销售数据集dfpd.DataFrame({date:[2026-01-01,2026-01-02,2026-01-03],sales:[100,150,200]})# 方法1: 先将date列转换为datetime类型df[date]pd.to_datetime(df[date])# 方法2: 直接设置为索引ts_dfdf.set_index(date)print(ts_df.index)# DatetimeIndex# 或者一步到位ts_dfpd.read_csv(sales.csv,parse_dates[date],index_coldate)1.3 处理时区Timezone在全球化业务中处理不同时区的数据至关重要。# 创建一个带有时区信息的时间戳ts_utcpd.Timestamp(2026-04-03 14:30:00,tzUTC)print(ts_utc)# 2026-04-03 14:30:0000:00# 转换到上海时区ts_shanghaits_utc.tz_convert(Asia/Shanghai)print(ts_shanghai)# 2026-04-03 22:30:0008:00# 为一个没有时区的DatetimeIndex添加时区ts_df.indexts_df.index.tz_localize(UTC).tz_convert(Asia/Shanghai)第二章时间序列的核心操作——选择、重采样与滚动计算一旦数据被正确索引强大的时间操作就触手可及。2.1 时间序列的选择与切片得益于DatetimeIndex我们可以像使用字符串一样直观地进行切片。# 假设ts_df是一个以日期为索引的销售数据# 选择某一天single_dayts_df.loc[2026-01-15]# 选择某个月jan_2026ts_df.loc[2026-01]# 选择一个日期范围q1_2026ts_df.loc[2026-01-01:2026-03-31]# 使用部分字符串索引Partial String Indexingts_df[2026]# 整年ts_df[2026-02]# 2月2.2 重采样Resampling改变时间频率这是时间序列分析中最常用的操作之一。它可以将高频数据聚合为低频数据降采样或将低频数据填充为高频数据升采样。降采样示例日数据 - 月数据# 计算每月总销售额monthly_salests_df[sales].resample(M).sum()# M代表月末# 计算每月平均销售额monthly_avgts_df[sales].resample(M).mean()升采样示例日数据 - 小时数据# 将日数据上采样到小时并用向前填充ffill来填补空缺hourly_datats_df[sales].resample(H).ffill()常用频率别名D: 日W: 周M: 月末MS: 月初Q: 季末AorY: 年末2.3 滚动窗口Rolling Window计算滚动窗口允许我们在一个滑动的固定大小窗口内进行计算这对于平滑噪声、计算移动平均等非常有用。# 计算7天的移动平均销售额ts_df[rolling_mean_7d]ts_df[sales].rolling(window7).mean()# 计算30天的滚动标准差ts_df[rolling_std_30d]ts_df[sales].rolling(window30).std()# 可视化原始数据和移动平均线importmatplotlib.pyplotasplt ts_df[[sales,rolling_mean_7d]].plot(figsize(12,6))plt.title(Sales with 7-Day Moving Average)plt.show()第三章洞察模式——时间序列分解原始的时间序列往往是趋势、季节性和随机噪声的混合体。时间序列分解Time Series Decomposition就是将它们分离开来的过程。3.1 经典分解模型一个时间序列Y t Y_tYt通常可以被建模为加法模型:Y t T t S t R t Y_t T_t S_t R_tYtTtStRt乘法模型:Y t T t × S t × R t Y_t T_t \times S_t \times R_tYtTt×St×Rt其中T t T_tTt是趋势Trend成分代表长期的上升或下降。S t S_tSt是季节性Seasonal成分代表固定周期内的重复模式如每周、每年。R t R_tRt是残差Residual或不规则Irregular成分代表无法被趋势和季节性解释的随机波动。3.2 使用statsmodels进行STL分解statsmodels库提供了强大的STLSeasonal and Trend decomposition using Loess分解方法它比传统的经典分解更为稳健。fromstatsmodels.tsa.seasonalimportSTLimportmatplotlib.pyplotasplt# 假设我们有一个名为airline_passengers的月度时间序列# 加载数据datapd.read_csv(airline_passengers.csv,parse_dates[Month],index_colMonth)tsdata[#Passengers]# 执行STL分解stlSTL(ts,seasonal13)# seasonal参数应为周期的奇数倍月度数据周期为12故取13resultstl.fit()# 绘制分解结果fig,axesplt.subplots(4,1,figsize(12,10),sharexTrue)result.observed.plot(axaxes[0],titleOriginal)result.trend.plot(axaxes[1],titleTrend)result.seasonal.plot(axaxes[2],titleSeasonal)result.resid.plot(axaxes[3],titleResidual)plt.tight_layout()plt.show()通过分解我们可以清晰地看到航空乘客数量的强劲增长趋势、明显的年度季节性夏季高峰以及围绕趋势和季节性的随机波动。第四章从分析到预测——构建基准模型预测是时间序列分析的终极目标之一。在投入复杂的模型如ARIMA, Prophet, LSTM之前建立一个基准模型Baseline Model至关重要。它能帮助我们判断复杂模型是否真的带来了性能提升。4.1 常见的基准预测方法**朴素预测 **(Naive Forecast)明天的值等于今天的值。forecast(t1) actual(t)**季节性朴素预测 **(Seasonal Naive Forecast)下个周期的值等于上个周期同一位置的值。例如下周一的销售额等于本周一的销售额。**移动平均预测 **(Moving Average Forecast)用过去N个周期的平均值作为下一个周期的预测。4.2 实战构建并评估一个移动平均预测模型我们将使用一个简单的销售数据集来演示完整流程。步骤1准备数据和划分训练/测试集# 加载数据dfpd.read_csv(daily_sales.csv,parse_dates[date],index_coldate)tsdf[sales]# 划分数据保留最后30天作为测试集traints[:-30]testts[-30:]步骤2定义预测函数defmoving_average_forecast(series,window_size):计算移动平均预测forecastseries.rolling(windowwindow_size).mean()returnforecast.shift(1)# 预测t1时刻所以要shift(1)# 生成训练集上的预测用于查看拟合效果train_forecastmoving_average_forecast(train,window_size7)# 生成测试集上的预测# 注意测试集的预测需要基于训练集的最后几个点last_windowtrain[-7:].tolist()test_forecast[]for_inrange(len(test)):next_prednp.mean(last_window)test_forecast.append(next_pred)# 更新窗口移除最旧的加入最新的预测或实际值如果是模拟last_windowlast_window[1:][next_pred]# 这里用预测值递推test_forecastpd.Series(test_forecast,indextest.index)步骤3评估模型性能fromsklearn.metricsimportmean_absolute_error,mean_squared_error# 计算MAE和RMSEmaemean_absolute_error(test,test_forecast)rmsenp.sqrt(mean_squared_error(test,test_forecast))print(fTest MAE:{mae:.2f})print(fTest RMSE:{rmse:.2f})# 可视化结果plt.figure(figsize(12,6))plt.plot(train[-100:],labelTrain)plt.plot(test,labelActual)plt.plot(test_forecast,labelForecast,linestyle--)plt.legend()plt.title(7-Day Moving Average Forecast)plt.show()这个简单的模型虽然朴素但它提供了一个重要的性能基线。任何更复杂的模型都必须显著优于这个基线才有价值。第五章综合实战项目——分析与预测零售店月度销售额让我们整合本讲所学完成一个端到端的时间序列分析项目。项目背景你是一家零售连锁店的数据分析师。你需要分析过去5年的月度销售数据识别其趋势和季节性模式并为下一年提供初步的销售预测。数据集retail_sales.csv包含两列Month日期和Sales销售额。Python代码实现importpandasaspdimportnumpyasnpimportmatplotlib.pyplotaspltfromstatsmodels.tsa.seasonalimportSTLfromsklearn.metricsimportmean_absolute_percentage_error# 1. 数据加载与探索dfpd.read_csv(retail_sales.csv,parse_dates[Month],index_colMonth)print(df.head())print(df.info())# 可视化原始时间序列df[Sales].plot(figsize(12,6))plt.title(Retail Monthly Sales (2021-2026))plt.ylabel(Sales ($))plt.show()# 2. 时间序列分解stlSTL(df[Sales],seasonal13)resultstl.fit()# 绘制分解图fig,axesplt.subplots(4,1,figsize(12,10),sharexTrue)result.observed.plot(axaxes[0],titleObserved)result.trend.plot(axaxes[1],titleTrend)result.seasonal.plot(axaxes[2],titleSeasonal)result.resid.plot(axaxes[3],titleResidual)plt.tight_layout()plt.show()# 3. 检查平稳性通过观察残差# 一个理想的残差序列应该是均值为0、方差恒定的白噪声。result.resid.plot(figsize(12,4))plt.title(Residuals after STL Decomposition)plt.show()# 4. 构建基准预测模型季节性朴素预测# 划分数据保留最后12个月一年作为测试集traindf[Sales][:-12]testdf[Sales][-12:]# 季节性朴素预测下一年的每个月 上一年同月的值seasonal_naive_forecasttrain[-12:].values# 取训练集最后12个月# 5. 评估模型mapemean_absolute_percentage_error(test,seasonal_naive_forecast)print(fSeasonal Naive Forecast MAPE:{mape:.2%})# 6. 可视化预测结果plt.figure(figsize(12,6))plt.plot(train[-24:],labelTrain (Last 2 Years))plt.plot(test,labelActual,markero)plt.plot(test.index,seasonal_naive_forecast,labelSeasonal Naive Forecast,markerx,linestyle--)plt.legend()plt.title(Retail Sales Forecast for Next Year)plt.ylabel(Sales ($))plt.show()# 7. 生成未来12个月的预测用于报告future_datespd.date_range(starttest.index[-1]pd.DateOffset(months1),periods12,freqMS)future_forecastpd.Series(seasonal_naive_forecast,indexfuture_dates)print(\n Next Years Sales Forecast )print(future_forecast)这个项目完整地展示了从数据加载、模式识别分解、模型构建、评估到最终预测输出的全过程是时间序列分析的标准工作流。结语与展望恭喜你你已经成功完成了《Python数据分析筑基》系列的第九讲。我们不仅深入挖掘了Pandas在时间序列处理上的强大功能更重要的是建立了严谨的时间序列分析思维理解了如何通过分解洞察数据内在模式并通过构建基准模型为预测任务设定合理的期望。现在你的数据分析能力已经覆盖了数据的三大核心维度实体Who/What、空间Where和时间When。这为你解决绝大多数现实世界的商业和科研问题奠定了坚实的基础。下一步是什么在最后一讲中我们将进行一次综合大演练。我们将回顾整个系列的核心知识点并通过一个贯穿多个领域的综合性项目将所有技能融会贯通。你将体验到从数据获取SQL/Web Scraping、处理Pandas、空间分析GeoPandas、时间序列分析到机器学习建模Scikit-learn的完整数据科学工作流。敬请期待第十讲终章《融会贯通构建端到端的数据分析项目》FAQ常见问题解答Q1: 如何处理时间序列中的缺失值A: 处理方法取决于缺失的原因和程度前向填充ffill/后向填充bfill适用于少量连续缺失。插值interpolate如线性插值、时间插值适用于有明显趋势的数据。使用模型预测填充对于大量缺失可能需要更复杂的策略。Q2: 什么是“未来信息泄露”Look-ahead BiasA: 这是在时间序列预测中常见的致命错误。指在训练模型时不小心使用了在预测时刻之后才发生的信息。例如在用滚动窗口计算特征时如果窗口包含了未来数据就会导致模型在回测中表现虚高但在真实预测中失效。永远确保你的特征只依赖于过去和当前的信息。Q3: STL分解中的seasonal参数如何选择A:seasonal参数应设置为季节性周期的整数倍并且最好是奇数。对于月度数据周期12通常选择13对于季度数据周期4选择5或7。可以通过尝试不同的值并观察分解结果的平滑度来微调。扩展阅读推荐官方文档Pandas Time Series User GuideStatsmodels Time Series Analysis经典书籍《Forecasting: Principles and Practice》 by Rob J Hyndman and George Athanasopoulos - 免费在线阅读理论与实践结合的典范。在线课程Coursera上的《Practical Time Series Analysis》 - 提供了扎实的理论基础和Python实践。作者培风图南以星河揽胜创作不易如果觉得本文对你有帮助欢迎点赞、收藏、评论、关注你的支持是我持续创作的最大动力
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2491659.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!