简介这是一份基于Python的天气预测与可视化课程设计项目面向Python初学者、数据分析爱好者以及需要完成课程设计的高校学生。压缩包共24个文件包含4个Python源码负责数据获取、处理、建模与天气网页展示、4个CSV数据集、12张运行效果截图、1个Markdown说明文档及模型文件整体仅1.43MB。项目源自已获导师指导并通过的97分高分课设提供从数据爬取、清洗到模型训练与可视化呈现的完整可运行流程。目前已有653人学习下载可直接作为期末大作业或课程设计参考下载解压即可运行省去环境调试与代码修改的时间。1. 天气预测与可视化这份代码包解决什么问题做课程设计最怕的不是题目难而是“代码能跑但不知道在跑什么”。这份基于 Python 的天气预测与可视化源码包把数据采集、预处理、模型训练、结果可视化的完整链路都串好了不是那种只贴一个算法文件的半成品。压缩包里能看到 GetData.py数据抓取、ProcessData.py数据处理、GetModel.py模型训练、main.py主程序入口、Model.pkl训练好的模型、天气网.html可视化页面外加 train/valid/test 三份 CSV 和一份 china_today.csv。也就是说从原始天气数据到前端图表展示中间每一步都有对应脚本改参数就能换城市、换模型、换预测时长。适合两类人一是要做课程设计或期末大作业的在校生拿到的是一套能直接运行、有文档有数据的完整项目二是想快速上手“Python 爬虫 机器学习 Web 可视化”这套组合的初学者用真实天气数据走一遍全流程。2. 项目结构与数据流爬虫、预处理、建模、可视化四段式2.1 文件清单与职责划分解压后你会看到这些文件先别急着跑 main.py花两分钟把每个文件的角色搞清楚后面排错会省很多时间。文件职责关键说明GetData.py天气数据采集从公开天气接口或网页抓取历史天气输出 date_train.csv / date_valid.csv / date_test.csvProcessData.py数据清洗与特征工程处理日期格式、缺失值、归一化生成模型可用的特征矩阵GetModel.py模型训练与保存读取处理后的数据训练回归模型输出 Model.pklModel.pkl训练好的模型文件GetModel.py 的产物main.py 直接加载做预测main.py主程序入口加载模型、执行预测、调用可视化面向最终用户天气网.html可视化页面展示历史温度曲线、预测温度曲线、误差区域china_today.csv当日各城市天气快照可视化页面的补充数据用于城市对比readme.md项目说明文档运行步骤、环境依赖、注意事项我一般会建议先把 readme.md 打开看一眼确认 Python 版本和依赖库列表。这个项目用到的主要是 requests、pandas、numpy、scikit-learn、matplotlib 或 pyecharts 这类常见库环境配起来不折腾。2.2 数据流动方向从网页到浏览器图表整个项目的数据流是一条直线理解这条线就理解了全部代码。# 顺序执行三步就能从原始数据跑到可视化 python GetData.py # 抓取历史天气数据生成三个 CSV python ProcessData.py # 清洗并构造特征输出处理后的训练/验证数据 python GetModel.py # 训练模型并保存为 Model.pkl python main.py # 加载模型预测并启动可视化页面先解释为什么是这样一个执行顺序。GetData.py 负责把“外部世界”的天气数据落盘成 CSV这是整个项目的数据源头ProcessData.py 读入 CSV 后做特征工程因为原始数据里只有日期、最高温、最低温、天气状况这些字段模型没法直接用必须转换成数值特征GetModel.py 在这些特征上训练模型并序列化保存避免每次运行都重新训练最后 main.py 把模型和新的输入数据结合起来输出预测结果并提供可视化入口。这里有一个容易被忽略的细节Model.pkl 是训练产物如果你换了一批新数据或者改了 ProcessData.py 里的特征逻辑一定要重新运行 GetModel.py 重新训练否则 main.py 加载的还是旧模型。很多初学者跑完 GetModel.py 后改了数据回头直接跑 main.py发现预测结果离谱其实就是模型和数据不匹配。2.3 为什么用“脚本分步”而不是“一个 main 跑完”这是这个项目设计上比较聪明的地方。有人可能会问为什么不把所有逻辑都塞进 main.py双击一下全搞定实际上拆成多个脚本有三个实际好处。第一中间产物可以复用。GetData.py 跑一次可能要好几分钟取决于网速和抓取的城市数量如果每次都重新抓调试模型时效率很低。有了 CSV 中间文件ProcessData.py 和 GetModel.py 可以反复跑不用再碰网络请求。第二错误定位清晰。爬虫挂了、数据格式错了、模型分数低了分别对应不同脚本看回溯信息就知道去哪个文件里查而不是在一个几千行的 main.py 里大海捞针。第三符合课程设计的“模块化”评分点。大多数老师喜欢看到清晰的分层结构数据处理和模型训练分开写答辩的时候也更容易讲清楚。3. 数据预处理与特征工程ProcessData.py 的六个关键动作3.1 日期解析与时间特征拆解天气预测最基础的特征就是时间。ProcessData.py 里第一步通常是把 CSV 里的日期字符串转成 pandas 的 datetime 类型然后拆成年、月、日、星期几等特征。import pandas as pd df pd.read_csv(date_train.csv, encodingutf-8) df[date] pd.to_datetime(df[date], format%Y-%m-%d) df[year] df[date].dt.year df[month] df[date].dt.month df[day] df[date].dt.day df[weekday] df[date].dt.weekday df df.drop(columns[date]) # 原始日期列在拆解后可以删掉 print(df.head())这里要解释一个关键点模型不认识“2024-03-15”这种字符串它只认识数字。把日期拆成年月日和星期几相当于把时间信息转换成模型能吃的数值特征。year 和 month 能捕捉季节性趋势weekday 能捕捉周内波动——比如工作日和周末的温差这在城市天气预测里是真实存在的模式。参数说明format%Y-%m-%d是日期格式模板如果原始数据是“2024/3/15”这种写法需要改成%Y/%m/%d。dt.weekday返回 0-60 代表周一6 代表周日不需要额外处理模型会把它当普通整数特征。3.2 缺失值与异常值的处理策略天气数据最常见的缺失原因是采集当天接口超时或字段缺失。ProcessData.py 用的是前向填充加均值填充的组合策略。# 数值列缺失用前向填充再补一轮均值填充兜底 num_cols [high_temp, low_temp, wind_speed, humidity] for col in num_cols: df[col] df[col].fillna(methodffill).fillna(df[col].mean()) # 异常值检测超过 3 倍标准差的点用前后两天均值替换 for col in [high_temp, low_temp]: mean, std df[col].mean(), df[col].std() mask (df[col] - mean).abs() 3 * std if mask.sum() 0: df.loc[mask, col] (df[col].shift(1) df[col].shift(-1)) / 2这段代码的逻辑分两层。fillna 先按时间顺序前向填充——昨天的温度和今天的温度通常接近用昨天的值补今天的空位是合理的但如果数据开头就缺失前向填充补不上均值填充兜底。异常值处理用 3 倍标准差作为阈值超过这个范围的点视为传感器或录入错误用前后两天均值替换。参数说明fillna(methodffill)是前向填充pandas 2.0 之后推荐写成df[col].ffill()更规范。3 倍标准差是个经验值如果数据本身波动很大可以放宽到 4 倍标准差但课程设计场景下 3 倍基本够用。3.3 天气状况的编码从文本到数值“晴”、“多云”、“小雨”这些天气状况是文本不能直接喂给模型。ProcessData.py 里做的是 LabelEncoder 或者手动映射。# 手动映射天气状况到数值比 LabelEncoder 更可控 weather_map { 晴: 1, 多云: 2, 阴: 3, 小雨: 4, 中雨: 5, 大雨: 6, 雷阵雨: 7, 小雪: 8 } df[weather_code] df[weather].map(weather_map).fillna(0) df df.drop(columns[weather])手动映射和 LabelEncoder 的区别在于手动映射让数值带有语义——数字越小天气越好数字越大天气越恶劣这在特征重要性分析时更容易解释。LabelEncoder 是纯按字母顺序或出现频率编码数值大小没有意义。注意fillna(0)这一段如果 CSV 里出现了 mapping 字典里没写的天气比如“霾”或“沙尘暴”map 会返回 NaN填 0 是当作“未知天气类型”处理不影响模型运行。3.4 滞后特征把“昨天”的信息带进来天气是连续变化的过程今天的温度大概率接近昨天。ProcessData.py 里构造了滞后 1 天和滞后 2 天的温度特征这能显著提升预测准确率。df[high_lag1] df[high_temp].shift(1) # 昨天最高温 df[high_lag2] df[high_temp].shift(2) # 前天最高温 df[low_lag1] df[low_temp].shift(1) # 昨天最低温 df df.dropna() # 滞后特征会引入 NaN直接丢弃前两行shift(1) 的作用是把整列往下移动一行第 i 行的high_lag1就是第 i-1 行的high_temp。为什么要加滞后特征因为天气系统有惯性光靠月份和星期几做预测相当于假设“3 月 15 日的温度和每年的 3 月 15 日一样”但实际天气受前几天影响更大。加了滞后特征后模型能学到“今天冷则明天大概率也冷”这类时间连续性规律。参数说明滞后阶数取 1 和 2 是折中方案。滞后期数太少模型记不住上周的天气模式滞后期数太多比如 lag7会让特征维度膨胀在数据量不大的情况下容易过拟合。3.5 训练集与验证集的时间序列切分Weather 数据的切分不能像普通分类任务那样随机打乱否则时间穿越——用未来的数据训练拿过去的数据验证指标会虚高。ProcessData.py 里用的是时间顺序切分。# 按时间顺序切分前 80% 训练后 20% 验证 train_size int(len(df) * 0.8) train_df df.iloc[:train_size].copy() valid_df df.iloc[train_size:].copy() train_df.to_csv(date_train_processed.csv, indexFalse, encodingutf-8) valid_df.to_csv(date_valid_processed.csv, indexFalse, encodingutf-8) X_train train_df.drop(columns[high_temp]) y_train train_df[high_temp] X_valid valid_df.drop(columns[high_temp]) y_valid valid_df[high_temp]时间序列切分和随机切分的本质区别在于天气预测的输入 X 和输出 y 之间有时间上的一一对应关系一旦打乱顺序模型就学到了“未来信息”。比如 1 月 5 日的特征和 1 月 6 日的标签被放到同一批训练数据里模型会钻空子而不是学规律。用iloc[:train_size]保留原始顺序前面的数据训练后面的数据验证这样验证集分数才有说服力。3.6 归一化让特征在同一尺度下参与计算温度、湿度、风速、风向编码这些特征的数值范围差异很大。ProcessData.py 里用 StandardScaler 做标准化让每个特征均值为 0、标准差为 1。from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_valid_scaled scaler.transform(X_valid) import joblib joblib.dump(scaler, scaler.pkl)fit_transform 和 transform 的区别在代码里体现得很清楚训练集上做 fit_transform验证集上只做 transform。原因在于 scaler 的参数均值和标准差必须只从训练集统计如果拿全量数据去 fit验证集的信息就泄漏到了训练阶段和随机切分类似也会造成虚高。标准化后模型训练会更稳定。对于线性模型和神经网络来说特征尺度差异大会让梯度更新不稳定对于随机森林这类树模型标准化影响不大但统一处理没有坏处。这里把 scaler 也存成 pkl 文件主程序预测新数据时要用同一个 scaler 转换。4. 模型训练与持久化GetModel.py、Model.pkl 与评估指标4.1 模型选型为什么选了随机森林而不是 LSTM这个项目的预测目标是连续温度值属于回归问题。常见选择有线性回归、随机森林、XGBoost、LSTM 等。GetModel.py 里主模型用的是随机森林回归这个选择在课程设计场景下有几个实在的理由。数据量决定模型复杂度。课程设计的天气数据通常是几百条到几千条LSTM 这种深度学习模型动辄需要上万条样本才能学到时序模式样本太少必然过拟合。随机森林对数据量要求没那么苛刻几百条数据也能跑。其次随机森林不需要特征标准化虽然前面做了也没坏处对异常值和缺失值容忍度高能减少很多预处理阶段的心力消耗。最后随机森林能输出特征重要性答辩的时候可以展示“模型认为前一天最高温对预测影响最大”比光给一个预测图更有说服力。线性回归也可以作为基线模型但天气和日期的关系是非线性的——3 月的温度和 9 月的温度都在 20 度上下但驱动因素完全不同线性模型很难表达这种非线性关系。随机森林天然支持非线性拟合所以作为主模型更合适。4.2 训练流程网格搜索找最优超参数GetModel.py 里用了 GridSearchCV 做超参数搜索核心是寻找最优的树数量和树深度。from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import GridSearchCV import pandas as pd train_df pd.read_csv(date_train_processed.csv, encodingutf-8) X_train train_df.drop(columns[high_temp]) y_train train_df[high_temp] param_grid { n_estimators: [100, 200, 300], max_depth: [None, 10, 20], min_samples_split: [2, 5, 10] } model RandomForestRegressor(random_state42) grid_search GridSearchCV( model, param_grid, cv3, scoringneg_mean_absolute_error, n_jobs-1, verbose1 ) grid_search.fit(X_train, y_train) best_model grid_search.best_estimator_ print(f最优参数: {grid_search.best_params_})这段代码里有几个参数值得细说。cv3表示 3 折交叉验证数据量本来就有限折数太多每折分到的数据更少评估结果方差大折数太少评估不稳定3 折是时间序列数据场景下的折中。scoringneg_mean_absolute_error是告诉 GridSearchCV 用负平均绝对误差作为打分标准——sklearn 的规则是分数越大越好所以 MAE 要取负号。n_jobs-1表示用所有 CPU 核并行搜索参数组合不多的情况下一般几十秒就能跑完。random_state42 这个参数一定要固定。随机森林的训练过程有随机性不固定随机种子的话每次跑出来的模型性能会有小幅度波动答辩时老师如果想复现固定种子才能得到一致结果。4.3 模型评估MAE、RMSE 和 R² 怎么配合着看训练完模型不能直接交差得用验证集算三个指标。GetModel.py 里会输出下面这段评估代码的结果。from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score import numpy as np y_pred best_model.predict(X_valid_scaled) y_true y_valid mae mean_absolute_error(y_true, y_pred) rmse np.sqrt(mean_squared_error(y_true, y_pred)) r2 r2_score(y_true, y_pred) print(fMAE: {mae:.3f}°C) print(fRMSE: {rmse:.3f}°C) print(fR²: {r2:.3f})三个指标各有各的用途。MAE 是平均绝对误差最直观——它的数值就是“平均每次预测偏差多少度”比如 MAE1.5 意味着平均偏差 1.5°C。RMSE 是均方根误差它对大误差更敏感如果有一天的预测偏差了 8°CRMSE 会被拉高MAE 可能只上升一点点所以 RMSE 能帮你发现“偶发的离谱偏差”。R² 是决定系数表示模型解释了目标变量多少比例的方差越接近 1 越好课程设计里 R² 能到 0.85 以上就已经是相当不错的水平。这里有个实际会遇到的情况MAE1.5°C 听起来不错但如果和基线比——比如用“昨天的温度作为今天的预测”这个傻瓜策略——发现基线 MAE 只有 1.8°C那你这个模型相对基线只提升了 0.3°C说服力不够。我当时做的时候加了一条对照实验在代码里把基线模型的指标也打印出来这一小段在答辩时非常加分。4.4 Model.pkl 的保存与加载规范训练完成后模型必须序列化保存否则下次运行 main.py 还要重新训练一遍。GetModel.py 里用 joblib 而不是 pickle 保存这是 scikit-learn 官方推荐的做法。import joblib joblib.dump(best_model, Model.pkl) joblib.dump(scaler, scaler.pkl) # main.py 里加载 model joblib.load(Model.pkl) scaler joblib.load(scaler.pkl)为什么用 joblibpickle 保存 scikit-learn 模型偶尔会遇到兼容性问题特别是模型内部有大量 NumPy 数组时joblib 对数组类型数据的序列化效率更高、兼容性更好。如果你换了一台机器运行 main.pyModel.pkl 和 scaler.pkl 必须放在同一目录下因为 main.py 加载模型后还要用同一个 scaler 做特征标准化scaler 和模型是绑定的少一个预测结果就是乱的。另一个容易被忽略的问题Python 小版本升级可能导致 pkl 文件加载失败。用 Python 3.8 训练保存的 Model.pkl换到 Python 3.11 环境加载偶尔会报ModuleNotFoundError或AttributeError。如果遇到这个问题回原环境重新跑一次 GetModel.py 生成新 pkl 就行不用改代码。5. 高频踩坑与排查编码、路径、pkl 兼容与过拟合的五条记录5.1 中文乱码导致 CSV 读取失败现象运行 ProcessData.py 时pandas 读取 CSV 后打印出来全是乱码或者训练时直接报UnicodeDecodeError。原因天气数据里包含中文城市名和天气状况文件保存和读取的编码不一致。Windows 下默认可能写成了 GBKPython 的 pandas 默认按 UTF-8 读取两边对不上就是乱码。解决统一用 UTF-8 处理所有文件。读取时显式指定编码写入时也强制指定。df pd.read_csv(date_train.csv, encodingutf-8) df.to_csv(date_train_processed.csv, indexFalse, encodingutf-8-sig)utf-8-sig比utf-8多了一个 BOM 头这样生成的 CSV 用 Excel 打开不会乱码对课程设计交报告很实用。如果你在 Windows 终端里看到错误也可以用encodinggbk读取旧文件后另存为 UTF-8但新写的代码一律按 UTF-8 来。5.2 日期解析失败格式不匹配现象pd.to_datetime报ValueError: time data 2024/3/15 does not match format %Y-%m-%d。原因CSV 里日期格式不统一有的是2024-03-15有的是2024/3/15。代码里写死了%Y-%m-%d遇到斜杠格式就抛异常。解决不要硬填 format让 pandas 自动解析或者人为统一格式。df[date] pd.to_datetime(df[date], formatmixed) # 或者不传 format让 pandas 自动推断 df[date] pd.to_datetime(df[date])formatmixed是 pandas 2.x 的新参数允许一列里混合多种日期格式。如果用的还是 pandas 1.x直接去掉 format 参数让 pandas 自己识别即可但识别速度会慢一些数据量几百条不影响。5.3 Model.pkl 加载报错版本不匹配现象main.py 里执行joblib.load(Model.pkl)报ModuleNotFoundError: No module named sklearn...或者AttributeError: RandomForestRegressor object has no attribute ...。原因模型是另一台机器、另一个环境保存的。scikit-learn 不同大版本之间的 pkl 兼容性并不完美比如 0.24 版训练的模型在 1.2 版加载经常出问题。解决优先保证训练和运行环境一致。如果你从压缩包里拿到的 Model.pkl 是作者在 Python 3.8 sklearn 1.0 环境下生成的你的环境假如是 Python 3.11 sklearn 1.3不要挣扎直接重跑 GetModel.py 重新训练一份。Train 一次也就几分钟的事比折腾兼容性快得多。5.4 爬虫抓取失败接口反爬或字段缺失现象运行 GetData.py 时请求超时或者返回的 JSON 里缺少 temperature 字段。原因天气网站或接口可能更新了参数结构或者短时间内请求次数过多触发了频控。课程设计里抓的数据量不大通常不是封 IP 的问题而是接口字段名变化。解决先打印原始响应定位问题再看字段映射关系。import requests import json url https://example.com/weather?citybeijing resp requests.get(url, timeout10) data resp.json() print(json.dumps(data, ensure_asciiFalse, indent2)[:500])把原始 JSON 打出来看找到实际字段名再改 GetData.py 里的解析逻辑。如果接口彻底失效可以换一个公开天气数据源只要保证输出的 CSV 字段名不变下游 ProcessData.py 和 GetModel.py 都不需要改。5.5 训练集 R² 很高、验证集很低过拟合现象训练集上 R² 高达 0.98验证集上只有 0.5预测曲线和真实曲线偏离很大。原因特征设计或超参数让模型把训练集背下来了。常见诱因有两个一是滞后特征太多模型过度依赖前一天数据进行记忆二是max_depthNone让树无限生长每棵树都记住了训练集的所有细节。解决控制树深度增加min_samples_split约束同时缩减滞后特征。model RandomForestRegressor( n_estimators200, max_depth10, min_samples_split5, random_state42 )max_depth10限制树最多分裂 10 层防止每棵树无限细分。min_samples_split5表示一个节点至少有 5 个样本才允许继续分裂这两个参数是抑制过拟合最直接的手段。特征方面滞后特征保留 lag1 和 lag2 就够了不要加 lag7 这种长周期特征除非数据量非常大。6. 可视化验证与进阶main.py 的预测对照与误差复盘6.1 main.py 的可视化实现逻辑main.py 是整个项目的门面它加载 Model.pkl 对验证集做预测然后用可视化库生成图表。核心流程是读取处理后的 CSV → 加载模型和 scaler → 预测 → 渲染到 HTML 页面。import pandas as pd import joblib from flask import Flask, render_template_string df pd.read_csv(date_valid_processed.csv, encodingutf-8) model joblib.load(Model.pkl) scaler joblib.load(scaler.pkl) X df.drop(columns[high_temp]) y_true df[high_temp] X_scaled scaler.transform(X) y_pred model.predict(X_scaled) # 构造可视化数据 chart_data pd.DataFrame({ date: pd.date_range(end2024-01-31, periodslen(y_true), freqD), true_temp: y_true.values, pred_temp: y_pred })这里有个关键点预测时只对 X 做 transform不做 fit_transform。因为 scaler 已经拟合好了新数据进来用它转换即可如果重新 fit 则数据分布一变之前的模型就白训了。project 里 Flask 是可选依赖实际可视化是生成一个 HTML 页面间隔显示历史温度、预测温度和误差区域。6.2 误差区域图比单根曲线更值得看的东西可视化页面上除了真实温度曲线和预测温度曲线最有价值的是误差区域。把预测值的置信带画出来能直观看出模型在哪段时间信心不足。实际做法是叠加多个模型的预测结果取分位数做上下界。import numpy as np import matplotlib.pyplot as plt residuals y_pred - y_true lower np.percentile(residuals, 5) # 5% 分位误差 upper np.percentile(residuals, 95) # 95% 分位误差 plt.figure(figsize(12, 5)) plt.plot(y_true, label真实温度, color#333333) plt.plot(y_pred, label预测温度, color#e74c3c, linestyle--) plt.fill_between( range(len(y_true)), y_pred lower, y_pred upper, color#e74c3c, alpha0.15, label误差区间 ) plt.legend() plt.xlabel(时间序列) plt.ylabel(温度 (°C)) plt.title(天气预测结果对照与误差区间) plt.savefig(prediction_validation.png, dpi150)误差区间图比单独的预测曲线信息量大得多区间窄的地方说明模型自信区间宽的地方说明预测不可靠。课程设计里你把这张图放进报告老师会认为你对结果有批判性思考而不是只会贴代码。6.3 用真实天气对比验证预测失效的模式模型训练完、可视化做完别急着写报告。拿着 Model.pkl 对最近一周的天气做预测然后和真实发布的天气对比这是最硬核的验证方式。具体做法是新建一个predict_future.py构造未来几天的特征输入跑一遍预测流程。import joblib import pandas as pd from datetime import datetime, timedelta model joblib.load(Model.pkl) scaler joblib.load(scaler.pkl) # 构造未来 5 天的输入特征 future_dates [datetime.now() timedelta(daysi) for i in range(1, 6)] future_df pd.DataFrame({ year: [d.year for d in future_dates], month: [d.month for d in future_dates], day: [d.day for d in future_dates], weekday: [d.weekday() for d in future_dates], high_lag1: [25.0] * 5, # 假定昨天温度实际应从最近数据取 high_lag2: [24.5] * 5, low_lag1: [18.0] * 5, }) X_future scaler.transform(future_df) preds model.predict(X_future) print(f未来 5 天预测最高温: {[round(p, 1) for p in preds]})注意这里的滞后特征——未来几天的 lag1 和 lag2 是未知的你没法和训练时一样拿“过去两天”的数据填。常见做法是用最近的真实观测值填充然后滚动预测预测出第 1 天把预测结果作为第 2 天的 lag1。这个滚动预测逻辑如果写好了项目深度直接提升一个档次。6.4 我踩过的那个坑希望你别再踩我这套代码包跑了不下十遍最后悔的一次是拿到的原始 CSV 里日期格式不统一当时没注意直接跑 ProcessData.py报错后一急就把所有数据中的日期列全删了重新爬结果 GetData.py 和 ProcessData.py 之间的字段对接对不上白白浪费了一个晚上。从那以后我每次拿到新数据都强制走一遍df.info()和df.head()的检查流程确认字段名、数据类型、缺失值占比之后再往下走宁可多花五分钟也不会盲跑脚本了。这个习惯帮我避开了很多数据层面的暗坑希望你也能养成——拿到任何项目的压缩包别急着跑 main.py先看数据长什么样、版本对不对、路径通不通再动手执行。希望帮到你。本文还有配套的精品资源点击获取