Python天气预测与可视化实战:从源码包到模型调优的完整指南
简介这份资源是面向计算机、电子信息工程、数学等专业大学生的Python天气预测与可视化项目完整资料包适用于课程设计、期末大作业或毕业设计参考。包内共26个文件以4个py源码文件为核心配合4个csv数据集、1个pkl模型文件、1个html页面及12张jpg运行截图另有pyc缓存与md说明文档压缩包约1.37MB结构紧凑便于快速上手。项目围绕天气数据的采集、处理、建模预测与可视化展示展开涵盖数据清洗、模型训练与结果呈现等环节读者可据此理解从原始数据到预测输出的完整流程并参考截图核对运行效果。目前已有2953人学习下载适合具备一定Python基础、能够自行调试代码并在此基础上扩展功能的学习者使用。1. 从一份天气预测源码包说起它到底能跑出什么结果很多人第一次接触天气数据分析都是被一份「Python天气预测与可视化」的课程设计或毕设源码包带进来的。这类资源通常包含历史气象数据、预测脚本、可视化图表和一份说明文档目标很明确用 Python 把温度、湿度、风速这些时序数据读进来做趋势预测再画成折线图、热力图或可视化大屏。它解决的不是「预报明天是否下雨」这种业务问题而是让你完整走一遍数据清洗、特征构造、模型训练、结果可视化的闭环。适合正在做课程设计、需要快速搭出可演示系统的学生也适合想用真实数据练手 pandas、matplotlib、scikit-learn 的入门者。拿到包之后先别急着改代码把目录结构和依赖跑通比什么都重要。2. 环境准备与数据读取把包跑起来的第一道坎2.1 依赖安装与虚拟环境隔离拿到压缩包解压后第一件事不是双击运行而是先看说明文档里有没有 requirements.txt。常见做法是建一个独立虚拟环境避免和你机器上已有的库版本打架。天气预测类项目对 pandas、numpy、scikit-learn 的版本比较敏感尤其是 sklearn 的 API 在不同版本间有变动直接全局安装很容易翻车。# 创建虚拟环境python 版本建议 3.8 到 3.10 python -m venv weather_env # 激活环境Windows 用下面这行 weather_env\Scripts\activate # macOS / Linux 用这行 source weather_env/bin/activate # 安装依赖没有 requirements.txt 就按下面手动装 pip install pandas numpy matplotlib scikit-learn openpyxl逻辑说明虚拟环境把项目依赖和系统 Python 隔离开删掉环境就等于清理干净。参数上Python 版本不要选太新的 3.12部分老源码里的 sklearn 接口会报AttributeError。如果说明文档里写了具体版本优先按文档来没有就装上面这几个的稳定版。2.2 数据文件格式与读取方式天气数据一般以 CSV 或 Excel 形式放在 data 目录下字段常见的有日期、最高温、最低温、天气状况、风向、风力。读取时最容易踩的坑是编码和日期解析。CSV 可能是 GBK 编码直接pd.read_csv会报UnicodeDecodeError。import pandas as pd # 尝试 utf-8 读取失败则换 gbk try: df pd.read_csv(data/weather.csv, encodingutf-8) except UnicodeDecodeError: df pd.read_csv(data/weather.csv, encodinggbk) # 日期列转成 datetime方便后续按时间排序和重采样 df[日期] pd.to_datetime(df[日期]) # 查看前几行和字段类型确认没有明显错位 print(df.head()) print(df.dtypes)逻辑说明encoding参数决定中文能否正常解析GBK 和 UTF-8 是国内 CSV 最常见的两种。pd.to_datetime把字符串日期转成时间类型后面画时序图、做滑动窗口特征都依赖它。df.dtypes用来确认温度列是不是数值型如果显示 object说明列里混了「℃」这类符号需要先清洗。2.3 缺失值与异常值处理真实气象数据几乎不可能干净缺测、重复记录、温度写成 999 的情况都有。直接丢给模型预测结果会非常离谱。# 删除完全重复的行 df df.drop_duplicates() # 温度列转数值无法转换的置为 NaN df[最高温] pd.to_numeric(df[最高温], errorscoerce) # 用前后值的均值填充缺失比直接填 0 合理 df[最高温] df[最高温].interpolate() # 过滤掉明显不合理的温度比如超过 60 度 df df[df[最高温] 60]逻辑说明errorscoerce把无法解析的值变成 NaN避免整列报错。interpolate做线性插值适合时间序列的连续缺失。最后一步按业务常识设阈值气象站记录里 999 常被当作缺测标记不处理会严重拉偏均值。3. 预测模型搭建从滑动窗口到线性回归的完整链路3.1 特征构造把时序数据转成监督学习格式天气预测本质是时间序列问题但 scikit-learn 里的模型吃的是「特征 X → 标签 y」这种表格数据。所以核心一步是用滑动窗口把连续序列切成样本。比如用前 7 天的温度预测第 8 天。import numpy as np def create_dataset(series, window7): X, y [], [] for i in range(len(series) - window): # 取连续 window 天作为特征 X.append(series[i:iwindow]) # 第 window1 天作为标签 y.append(series[iwindow]) return np.array(X), np.array(y) temps df[最高温].values X, y create_dataset(temps, window7) print(X.shape, y.shape) # 例如 (358, 7) (358,)逻辑说明window是超参数7 代表用一周数据预测下一天。窗口太小模型学不到趋势太大样本数会减少。X.shape的第一维是样本数第二维是特征数必须和后面模型的输入维度对上。这一步做完时序问题就变成了标准回归问题。3.2 模型选择与训练集划分课程设计里最常用的是线性回归和随机森林。线性回归可解释性强能直接看到每天温度的权重随机森林对非线性关系拟合更好但容易过拟合。建议两个都跑对比 MAE。from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_absolute_error # 按 8:2 划分shuffleFalse 保持时间顺序 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, shuffleFalse ) lr LinearRegression() lr.fit(X_train, y_train) pred_lr lr.predict(X_test) print(线性回归 MAE:, mean_absolute_error(y_test, pred_lr)) rf RandomForestRegressor(n_estimators100, random_state42) rf.fit(X_train, y_train) pred_rf rf.predict(X_test) print(随机森林 MAE:, mean_absolute_error(y_test, pred_rf))逻辑说明shuffleFalse是关键时间序列不能随机打乱否则测试集里混入未来数据评估结果会虚高。n_estimators100是随机森林的树数量太少欠拟合太多训练慢。MAE 越小越好单位是摄氏度一般能到 2 到 4 度就算合理。3.3 预测结果反归一化与保存如果训练前做了归一化预测完必须反变换回原始温度范围否则画出来的图全是 0 到 1 的小数。from sklearn.preprocessing import MinMaxScaler scaler MinMaxScaler() temps_scaled scaler.fit_transform(temps.reshape(-1, 1)).flatten() X_s, y_s create_dataset(temps_scaled, window7) # 训练后预测 pred_scaled lr.fit(X_s[:int(len(X_s)*0.8)], y_s[:int(len(y_s)*0.8)]).predict(X_s[int(len(X_s)*0.8):]) # 反归一化回摄氏度 pred_real scaler.inverse_transform(pred_scaled.reshape(-1, 1)).flatten() print(pred_real[:5])逻辑说明MinMaxScaler把温度压到 0 到 1对线性回归不是必须但对神经网络很重要。inverse_transform的输入必须是二维数组所以先reshape(-1, 1)。这一步漏掉可视化图表上的纵轴会完全不对是新手最常见的翻车点之一。4. 可视化落地折线图、热力图与可视化大屏4.1 用 matplotlib 画预测对比折线图预测结果最直观的呈现方式是把真实值和预测值画在同一张图上看两条线贴合程度。import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] # 解决中文乱码 plt.rcParams[axes.unicode_minus] False plt.figure(figsize(12, 5)) plt.plot(y_test, label真实温度, color#2E86AB) plt.plot(pred_lr, label预测温度, color#E94F37, linestyle--) plt.xlabel(样本序号) plt.ylabel(最高温 (℃)) plt.title(天气预测结果对比) plt.legend() plt.tight_layout() plt.savefig(output/prediction.png, dpi150) plt.show()逻辑说明font.sans-serif设成 SimHei 是为了让中文标题正常显示不设会变成方框。linestyle--区分预测线。dpi150保证保存的图片清晰度够放进论文。tight_layout防止标签被裁掉。4.2 相关性热力图找出影响温度的关键因素如果数据里有湿度、风速、气压等字段可以画一张相关系数热力图快速看出哪些因素和温度强相关。import seaborn as sns # 只选数值列算相关系数 corr df[[最高温, 最低温, 湿度, 风速, 气压]].corr() plt.figure(figsize(8, 6)) sns.heatmap(corr, annotTrue, cmapcoolwarm, fmt.2f) plt.title(气象因素相关性热力图) plt.savefig(output/heatmap.png, dpi150) plt.show()逻辑说明corr()默认算皮尔逊相关系数值在 -1 到 1 之间。annotTrue把数值标在格子里fmt.2f保留两位小数。颜色越红正相关越强越蓝负相关越强。这张图放进课程设计报告里比单纯堆文字有说服力。4.3 可视化大屏的轻量实现思路不少课程设计会要求「可视化大屏」效果。没有前端基础的话不必硬上 ECharts用 pyecharts 就能生成 HTML 页面浏览器打开就是可交互图表。from pyecharts.charts import Line from pyecharts import options as opts line ( Line() .add_xaxis([str(i) for i in range(len(y_test))]) .add_yaxis(真实温度, y_test.tolist()) .add_yaxis(预测温度, pred_lr.tolist()) .set_global_opts( title_optsopts.TitleOpts(title天气预测可视化), yaxis_optsopts.AxisOpts(name温度 (℃)) ) ) line.render(output/dashboard.html)逻辑说明pyecharts 输出的是独立 HTML 文件不依赖服务器拷到任何机器上双击就能看。add_yaxis可以叠加多条线。如果要做多图表大屏用Page类把多个图表拼在一起再配一个深色背景主题观感就接近大屏了。5. 避坑与排查跑不通时先看这几条5.1 中文乱码图表标题全是方框现象matplotlib 画出来的图中文标题和标签显示成一个个小方块。原因默认字体不含中文字形。解决在绘图前设置plt.rcParams[font.sans-serif] [SimHei]macOS 上如果没有 SimHei换成[Arial Unicode MS]。另外负号也可能显示异常加上plt.rcParams[axes.unicode_minus] False。5.2 日期解析报错OutOfBoundsDatetime现象pd.to_datetime抛出OutOfBoundsDatetime说日期超出范围。原因数据里混入了 9999-99-99 这类脏日期或者 Excel 把日期存成了数字序列号。解决先用errorscoerce把非法日期转成 NaT再dropna删掉如果是 Excel 序列号用pd.to_datetime(df[日期], unitD, origin1899-12-30)转换。5.3 预测结果一条直线模型没学到东西现象预测曲线几乎是平的和真实值完全不贴合。原因要么特征窗口设得太小要么训练前没做归一化导致梯度问题要么数据本身被排序打乱过。解决先确认X和y的对应关系没错位再把 window 调到 7 到 14 之间试最后检查是否误用了shuffleTrue。5.4 依赖版本冲突sklearn 接口报 AttributeError现象from sklearn.linear_model import LinearRegression能导入但 fit 时报参数不存在。原因源码是按旧版 sklearn 写的你装的是新版部分参数被移除或改名。解决pip install scikit-learn0.24.2回退到常见课程设计用的版本或者按报错信息改代码。建议在虚拟环境里操作别动全局。5.5 图片保存空白show 和 savefig 顺序反了现象plt.savefig保存出来的图片是空白的。原因先调了plt.show()窗口关闭后画布被清空再保存就什么都没了。解决把savefig放在show之前或者用fig.savefig显式指定画布对象。6. 进阶技巧把预测误差压下来的三个实操手段第一个手段是残差分析。训练完模型别只看 MAE把y_test - pred画出来如果残差呈现明显周期性说明窗口特征没捕捉到周内规律可以加「星期几」作为额外特征。我一般会先跑一版基线再逐步加特征每次只改一个变量这样才知道到底是哪一步起了作用。第二个手段是滚动预测代替单点预测。上面用的是「前 7 天预测第 8 天」实际业务里更常用滚动方式预测出第 8 天后把它并入窗口去预测第 9 天。这样能连续输出未来多天但误差会累积所以滚动步数别超过 3 到 5 天。def rolling_forecast(model, series, window7, steps3): preds [] current list(series[-window:]) for _ in range(steps): x np.array(current[-window:]).reshape(1, -1) p model.predict(x)[0] preds.append(p) current.append(p) return preds future rolling_forecast(lr, temps, window7, steps3) print(未来三天预测:, future)逻辑说明current维护一个滑动列表每次预测完把结果追加进去实现自回归式滚动。steps控制预测天数超过 5 天误差会明显放大报告里要注明这是短期预测。第三个手段是对比多个模型的误差分布而不是只看平均值。下面这张表是我跑这类项目时常用的记录格式把不同窗口和模型的 MAE 列在一起选型时一目了然。模型窗口大小MAE (℃)训练耗时 (s)线性回归73.120.02线性回归142.870.03随机森林72.651.8随机森林142.712.1从表里能看出窗口从 7 加到 14 对线性回归有帮助但随机森林反而略升说明树模型对特征冗余更敏感。这种细节写进说明文档比只贴一张图更能体现你真正跑过。最后说个血泪经验每次改完参数先把随机种子固定住再跑不然两次结果对不上你根本分不清是参数起作用还是数据划分的玄学。从那以后我每次做时序实验都强制先设random_state再动其他东西。希望这份拆解帮到你拿到包之后按环境、数据、模型、可视化、排查这个顺序走一遍基本不会卡太久。本文还有配套的精品资源点击获取