
简介这份资源面向计算机、电子信息工程、数学等专业的大学生适用于课程设计、期末大作业或毕业设计场景提供一套基于Python的天气预测与可视化完整参考方案。压缩包共26个文件约1.37MB包含4个py源码文件、4个csv数据集、1个pkl模型文件、1个html页面、1个md说明文档以及12张jpg运行截图和3个pyc缓存文件覆盖数据获取、处理、建模与可视化全流程。其中源码模块分工明确涉及天气数据抓取、数据清洗与特征处理、模型训练与预测等环节csv数据可直接用于复现实验说明文档帮助理解整体思路截图则直观展示可视化效果。目前已有2953人学习下载适合具备一定Python基础、能够自行调试代码并在此基础上添加功能或修改逻辑的读者作为参考资料快速搭建天气预测项目框架理解从数据到预测结果的完整实现路径。1. 天气预测项目拆开看Python 能做的三件事和做不到的一件事拿到「基于 Python 天气预测与可视化源码数据说明文档」这类压缩包多数人第一反应是解压、装依赖、跑 main然后对着报错发呆。我见过太多人卡在这一步环境里 pandas 版本不对、matplotlib 中文字体缺失、数据文件路径写死成作者本机目录。这个标题真正值钱的地方不是「预测」两个字而是它把一条完整链路塞进了一个可运行工程——数据读取、特征构造、模型训练、结果可视化、说明文档。你要复现的不是某个神秘算法而是这条链路怎么在本地跑通、怎么换成自己的城市和数据、怎么把图做得能放进汇报材料。适合谁看会一点 Python 语法、装过 Anaconda 或 VS Code、想拿一个完整小项目练手的学生和转行者也适合需要快速搭一个天气数据看板、但不想从零写爬虫和绘图代码的开发者。不适合谁指望靠一个压缩包直接发论文或做业务级预报的人。天气预测的精度上限由数据源和预报时效决定Python 只是把已有数据算得更清楚、画得更直观。先把预期放正后面每一步才不会翻车。2. 跑通源码前环境、数据、目录三件事定生死2.1 用 conda 建独立环境别在 base 里硬装这类项目最常见的依赖组合是 pandas numpy scikit-learn matplotlib有时加 requests 或 openpyxl。版本冲突是头号杀手尤其是 pandas 2.x 和旧版代码里的append、inplace写法。我一般先建一个干净环境再按报错逐个补包而不是一次性pip install -r requirements.txt然后看它红一片。# 创建独立环境Python 版本选 3.9 或 3.10兼容性最好 conda create -n weather python3.10 -y conda activate weather # 先装数值和绘图三件套指定较稳的版本区间 pip install pandas1.5,2.2 numpy1.23,2.0 matplotlib3.6,3.9 pip install scikit-learn1.2,1.5 openpyxl requests # 验证关键包能否导入避免跑一半才报错 python -c import pandas, numpy, sklearn, matplotlib; print(ok)逻辑说明先锁 Python 版本是因为很多老项目的sklearn接口在 3.11 以上会有警告甚至行为变化。pandas 上限卡在 2.2 以下是为了避开部分旧代码里已被移除的DataFrame.append。最后一行导入验证不是多余它能提前暴露 DLL 缺失、numpy 与 pandas 二进制不匹配这类问题。参数上如果你机器上已有 GPU 且项目带深度学习部分再考虑装 torch否则不要引入纯 CPU 的 sklearn 足够跑通天气回归和分类任务。2.2 数据文件先做体检再谈建模压缩包里的数据通常是 CSV 或 Excel字段可能叫date、temp、humidity、pressure、wind也可能用中文列名。不要直接read_csv就扔进模型先看形状、缺失、时间范围。import pandas as pd # 读取时先不解析日期避免格式不统一直接报错 df pd.read_csv(data/weather.csv, encodingutf-8) print(形状:, df.shape) print(列名:, df.columns.tolist()) print(缺失值:\n, df.isna().sum()) print(前五行:\n, df.head()) # 尝试解析日期列errorscoerce 把无法解析的变成 NaT方便统计 df[date] pd.to_datetime(df[date], errorscoerce) print(日期范围:, df[date].min(), 到, df[date].max()) print(无法解析的日期数:, df[date].isna().sum())逻辑说明encoding参数很关键中文数据常见gbk或utf-8-sig读出来乱码就换。errorscoerce是后悔药它不会让脚本崩而是把脏日期标成 NaT你后面可以决定是删还是填。参数上如果数据量超过几十万行read_csv加parse_dates[date]会更快但前提是格式统一。体检完你要回答三个问题时间跨度够不够训练、缺失比例是否超过 20%、目标列是哪一列。目标列通常是温度或天气类型这决定你后面用回归还是分类。2.3 目录结构别照搬按「数据-代码-输出」重排作者本机的目录往往带绝对路径比如C:\Users\xxx\Desktop\weather\data。你解压后第一件事是重排成相对路径结构否则换台机器就废。weather_project/ ├── data/ │ ├── raw/ # 原始数据只读不改 │ └── processed/ # 清洗后数据 ├── src/ │ ├── preprocess.py │ ├── train.py │ └── visualize.py ├── outputs/ │ ├── figures/ │ └── models/ └── README.md逻辑说明raw只读是血泪经验清洗脚本写错时你还能回到原点。processed存中间结果方便对比不同清洗策略。outputs分开存图和模型避免覆盖。改路径时全局搜索C:\、/Users/、Desktop这类字符串换成Path(__file__).parent相对定位。参数上如果项目用os.path建议逐步换成pathlib跨平台更稳。3. 预测部分怎么落地从特征到模型的最小闭环3.1 时间特征构造把日期拆成模型能吃的数字天气数据本质是时间序列但很多入门项目直接当普通回归做。你要先构造时间特征让模型理解「月份」「季节」「星期」的影响。import pandas as pd import numpy as np df pd.read_csv(data/processed/clean.csv, parse_dates[date]) df df.sort_values(date).reset_index(dropTrue) # 基础时间特征 df[month] df[date].dt.month df[dayofyear] df[date].dt.dayofyear df[weekday] df[date].dt.weekday # 周期性编码让 12 月和 1 月在数值上接近而不是相差 11 df[month_sin] np.sin(2 * np.pi * df[month] / 12) df[month_cos] np.cos(2 * np.pi * df[month] / 12) # 滞后特征用前几天的温度预测今天 for lag in [1, 2, 3, 7]: df[ftemp_lag_{lag}] df[temp].shift(lag) # 滑动窗口均值 df[temp_roll_7] df[temp].rolling(window7, min_periods1).mean() df df.dropna().reset_index(dropTrue) print(df[[date, temp, month_sin, temp_lag_1, temp_roll_7]].head())逻辑说明month_sin和month_cos是周期编码的核心普通整数月份会让模型以为 12 月到 1 月是断崖。滞后特征shift模拟「用历史预测未来」注意shift(1)表示前一天不能把当天温度当特征否则就是数据泄露。rolling的min_periods1保证开头不产生 NaN。参数上滞后阶数不是越多越好天气数据一般 1、2、3、7 够用太多会引入噪声和缺失。如果你预测的是天气类型而非温度把temp换成类别列滞后特征改用众数或前一天的类别编码。3.2 训练集测试集怎么切时间序列不能随机打乱这是新手最容易翻车的地方。用train_test_split随机切会把未来数据混进训练集测试分数虚高上线就崩。from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_absolute_error, r2_score feature_cols [ month_sin, month_cos, dayofyear, weekday, temp_lag_1, temp_lag_2, temp_lag_3, temp_lag_7, temp_roll_7 ] target_col temp # 按时间顺序切分前 80% 训练后 20% 测试 split_idx int(len(df) * 0.8) train df.iloc[:split_idx] test df.iloc[split_idx:] X_train, y_train train[feature_cols], train[target_col] X_test, y_test test[feature_cols], test[target_col] model RandomForestRegressor( n_estimators200, max_depth12, min_samples_leaf3, random_state42, n_jobs-1 ) model.fit(X_train, y_train) pred model.predict(X_test) print(MAE:, round(mean_absolute_error(y_test, pred), 2)) print(R2:, round(r2_score(y_test, pred), 3))逻辑说明iloc按位置切分保证时间顺序前段训练后段测试模拟真实预测场景。RandomForestRegressor对缺失和量纲不敏感适合入门。n_estimators200是精度和速度的平衡点max_depth12防止过拟合min_samples_leaf3让叶子节点不过细。n_jobs-1用满 CPU。参数上如果 MAE 大于 3 摄氏度先检查特征里有没有泄露、滞后是否错位如果 R2 为负说明模型还不如直接拿前一天温度当预测回到数据清洗阶段。想换模型GradientBoostingRegressor或XGBRegressor通常更准但调参成本更高入门先用随机森林把闭环跑通。3.3 模型持久化与预测新数据跑通一次不够你要能把模型存下来下次直接加载预测。import joblib # 保存模型和特征列缺一不可 joblib.dump({model: model, features: feature_cols}, outputs/models/weather_rf.pkl) # 加载并预测一条新样本 bundle joblib.load(outputs/models/weather_rf.pkl) new_sample pd.DataFrame([{ month_sin: 0.5, month_cos: 0.866, dayofyear: 120, weekday: 2, temp_lag_1: 18.5, temp_lag_2: 17.9, temp_lag_3: 19.1, temp_lag_7: 18.0, temp_roll_7: 18.3 }]) print(预测温度:, round(bundle[model].predict(new_sample[bundle[features]])[0], 2))逻辑说明把特征列和模型一起存是因为加载时如果列顺序或名称不一致sklearn 会报错或给出错误结果。joblib比 pickle 更适合 numpy 数组。参数上新样本的构造必须和训练时完全一致尤其是周期编码和滞后值。实际使用时滞后值来自最近几天的真实观测不能凭空填。如果你要做滚动预测就用预测值回填滞后列但误差会累积一般只往前推 1 到 3 天。4. 可视化怎么做才不像默认截图图表选型与中文字体4.1 中文字体配置一次配好全局生效matplotlib 默认字体不含中文图里全是方框。这是最高频的翻车点。import matplotlib.pyplot as plt import matplotlib # Windows 常用 SimHeimacOS 用 Arial Unicode MSLinux 用 WenQuanYi matplotlib.rcParams[font.sans-serif] [SimHei, Arial Unicode MS, WenQuanYi Micro Hei] matplotlib.rcParams[axes.unicode_minus] False # 负号正常显示 fig, ax plt.subplots(figsize(10, 4)) ax.plot(df[date], df[temp], label实际温度) ax.set_title(温度变化趋势) ax.set_xlabel(日期) ax.set_ylabel(温度) ax.legend() plt.tight_layout() plt.savefig(outputs/figures/temp_trend.png, dpi150)逻辑说明font.sans-serif给一个列表matplotlib 会按顺序找系统里存在的字体。axes.unicode_minusFalse解决负号变方框。tight_layout防止标签被裁。dpi150适合放进文档屏幕展示 100 就够。参数上如果服务器没有中文字体把字体文件放到项目里用font_manager.fontManager.addfont注册再指定字体名。4.2 预测对比图让误差一眼可见只画一条预测线没有说服力要把实际值、预测值、误差带放一起。fig, axes plt.subplots(2, 1, figsize(12, 7), sharexTrue) # 上图实际 vs 预测 axes[0].plot(test[date], y_test, label实际, color#1f77b4) axes[0].plot(test[date], pred, label预测, color#ff7f0e, linestyle--) axes[0].set_ylabel(温度) axes[0].legend() axes[0].set_title(测试集预测对比) # 下图残差 residual y_test.values - pred axes[1].bar(test[date], residual, color#2ca02c, alpha0.6) axes[1].axhline(0, colorblack, linewidth0.8) axes[1].set_ylabel(残差) axes[1].set_xlabel(日期) plt.tight_layout() plt.savefig(outputs/figures/pred_vs_actual.png, dpi150)逻辑说明上下两图共享 x 轴方便对齐时间。残差图能暴露系统性偏差比如模型在高温段总是低估。alpha让柱状图不遮挡网格。参数上如果日期太密用fig.autofmt_xdate()旋转标签或只显示每月刻度。颜色选对比明显的别用红绿组合考虑色盲用户。4.3 可视化大屏思路从静态图到可交互热词里「可视化大屏」出现频率很高但天气项目不必上重型前端。用plotly或pyecharts生成 HTML浏览器打开就能交互成本最低。import plotly.express as px fig px.line( df, xdate, ytemp, title交互式温度趋势, labels{date: 日期, temp: 温度} ) fig.update_layout( hovermodex unified, templateplotly_white ) fig.write_html(outputs/figures/interactive_temp.html) print(已生成交互图)逻辑说明plotly.express一行出图hovermodex unified让鼠标悬停显示同一时间点的所有值。write_html输出单文件发给别人不用装环境。参数上数据量超过一万行时 plotly 会卡先按天聚合再画。如果要做大屏把多个 HTML 用 iframe 嵌到一个页面或用dash起本地服务但那是另一个工程量级入门先用静态 HTML 验证需求。5. 避坑与排查五个让项目跑不起来的真实原因5.1 现象KeyError: temp列名对不上原因数据文件列名可能是Temperature、温度或带空格。解决读入后先print(df.columns.tolist())用df.rename(columns{Temperature: temp})统一或在配置里维护列名映射。不要硬编码中文列名容易因编码问题失败。5.2 现象日期解析后全是 NaT原因日期格式混杂比如2023/1/1和2023-01-01同时存在。解决用pd.to_datetime(df[date], formatmixed, errorscoerce)或先统一替换分隔符。处理完统计 NaT 比例超过 5% 要考虑数据源是否可靠。5.3 现象模型 MAE 很小但预测图完全错位原因滞后特征用了shift(-1)或切分时打乱了顺序造成数据泄露。解决确认shift为正数切分用iloc按时间顺序训练集日期全部早于测试集。画图时检查 x 轴是否单调递增。5.4 现象保存的图中文变方框换台机器又好了原因字体依赖系统开发机有 SimHei服务器没有。解决把字体文件随项目分发用font_manager注册或在绘图前检测字体是否存在不存在则回退英文标签。不要假设运行环境和你本机一致。5.5 现象requirements.txt装完仍报版本冲突原因作者导出时没锁版本或混入了本机特有的包。解决不要盲目全装按报错逐个装核心包用pip install 包名版本锁定。核心包不超过十个其余按需。虚拟环境是后悔药装坏了删掉重建别在 base 里折腾。6. 把项目变成自己的换城市、换数据源、加验证跑通作者的数据只是起点。我一般会做三件事让它真正属于自己。第一换数据。把data/raw里的 CSV 替换成你所在城市的气象数据字段名对齐后重跑preprocess.py。如果原数据只有温度你可以用公开气象接口补湿度、气压但注意接口返回的字段名和频率按天聚合后再合并。第二加一个基线对比。用「前一天温度」作为预测值算 MAE如果随机森林打不过这个基线说明特征或切分有问题。这个习惯能帮你快速判断模型是否真的学到了东西。# 朴素基线直接用前一天温度预测今天 baseline_pred test[temp_lag_1] baseline_mae mean_absolute_error(y_test, baseline_pred) print(基线 MAE:, round(baseline_mae, 2)) print(模型 MAE:, round(mean_absolute_error(y_test, pred), 2)) print(提升:, round((baseline_mae - mean_absolute_error(y_test, pred)) / baseline_mae * 100, 1), %)逻辑说明基线是检验模型价值的标尺。如果提升不到 5%要么特征不够要么数据噪声太大。参数上temp_lag_1必须和测试集对齐不能有缺失。第三做滚动验证。把时间序列切成多个窗口每个窗口训练一次、预测下一段看 MAE 的波动。单次切分可能运气好滚动验证才能看出稳定性。from sklearn.model_selection import TimeSeriesSplit tscv TimeSeriesSplit(n_splits5) scores [] for train_idx, val_idx in tscv.split(df): tr, va df.iloc[train_idx], df.iloc[val_idx] m RandomForestRegressor(n_estimators100, max_depth10, random_state42, n_jobs-1) m.fit(tr[feature_cols], tr[target_col]) p m.predict(va[feature_cols]) scores.append(mean_absolute_error(va[target_col], p)) print(各折 MAE:, [round(s, 2) for s in scores]) print(平均 MAE:, round(sum(scores) / len(scores), 2))逻辑说明TimeSeriesSplit保证每折训练集都在验证集之前不泄露未来。n_splits5是常用值数据量小就减到 3。看各折分数是否稳定波动大说明数据分布变化剧烈可能需要按季节分开建模。参数上折数越多每折训练数据越少小数据集要权衡。最后说个习惯每次改完代码先跑一遍最小闭环——读数据、训模型、出图、存文件四步都过再去做优化。我见过太多人一上来就调参、换模型结果连数据都没对齐。这个项目最大的价值不是预测多准而是让你走通一条从原始数据到可视化输出的完整路径。把这条路径走熟换成销量预测、流量预测、能耗预测套路是一样的。希望帮到你。本文还有配套的精品资源点击获取