新闻详情

新闻详情

首页 / 资讯中心 / 详情

Python空气质量数据挖掘与机器学习预测模型实战

发布时间:2026/9/28 2:00:58来源:尧图网络
Python空气质量数据挖掘与机器学习预测模型实战
简介这份资源面向环境科学、数据挖掘与机器学习方向的学习者和研究者提供一套基于Python的空气质量数据可视化分析系统源码及配套数据。项目采用BS架构前端整合HTML、CSS、JavaScript与D3、ECharts、Mapbox等可视化库后端基于Python与Flask构建核心思路是先挖掘空气质量数据的时空特征通过降维聚类完成城市群划分再借助粒子输运与相关分析构建大气污染传输网络并利用多维空间变换的渐进式探索方法分析污染传播过程。压缩包共2000个文件以1295个json数据文件和697个py脚本为主另含少量txt、xml与md说明文档整体约76.43MB其中files目录存放原始数据与挖掘结果templates与static分别承载前端入口和静态资源。目前已有252人学习适合希望掌握空气质量分析全流程、复用可视化方案或开展相关课题研究的读者参考。1. 空气质量数据挖掘系统从原始 CSV 到可解释预测模型很多人第一次拿到空气质量数据集第一反应是直接df.describe()然后画个折线图交差。但真正做过这类项目的人都知道空气质量数据是典型的脏数据重灾区——传感器漂移、缺失值成片、PM2.5 和 PM10 高度共线、季节性和城市差异交织在一起。如果跳过数据挖掘直接上机器学习模型R² 看着漂亮一到真实预测就翻车。这个标题讲的事情很具体用 Python 把一份空气质量原始数据经过数据挖掘的清洗与特征工程再用机器学习建模最后用可视化把结论讲清楚。它适合两类人一类是正在做课程设计或毕业设计的学生需要一套能跑通、能解释、能答辩的完整链路另一类是刚转数据分析的工程师想找一个真实场景把 pandas、sklearn、ECharts 串起来。核心不是模型多复杂而是每一步为什么这么做、参数怎么定、哪里容易踩坑。2. 数据挖掘前的准备环境、数据字段与清洗策略2.1 环境搭建与依赖版本选择做空气质量分析环境不需要多花哨但版本冲突是新手第一个坑。我一般用 conda 建独立环境避免和系统 Python 打架。核心依赖就几个pandas 做数据挖掘、scikit-learn 做机器学习、matplotlib 和 pyecharts 做可视化、missingno 看缺失分布。# 创建独立环境Python 3.10 兼容性最稳 conda create -n air_quality python3.10 -y conda activate air_quality # 核心依赖指定版本区间避免 API 变动 pip install pandas2.0.3 numpy1.24.3 pip install scikit-learn1.3.0 pip install matplotlib3.7.2 pyecharts2.0.3 pip install missingno0.5.2 openpyxl3.1.2这里解释几个参数选择。pandas 锁 2.0.x 是因为 2.1 之后fillna的method参数被移除很多老教程代码会直接报错。scikit-learn 1.3 的HistGradientBoostingRegressor已经支持原生缺失值这对空气质量数据很关键。pyecharts 2.x 和 1.x 的 API 差异很大网上大量 ECharts 可视化代码是 1.x 写法混用会出问题。提示如果你用 VSCode 或 PyCharm记得把解释器切到刚建的air_quality环境否则 pip 装完 import 还是找不到。2.2 空气质量数据的典型字段与质量问题一份标准的空气质量数据集通常包含这些字段城市、监测站点、日期时间、AQI、PM2.5、PM10、SO2、NO2、CO、O3以及温度、湿度、风速、气压等气象列。数据挖掘阶段要盯住四类问题。第一类是缺失值。传感器故障会导致某个污染物整段缺失气象数据则常见单点缺失。第二类是异常值比如 PM2.5 出现 9999 这种标记值或者 CO 浓度突然为负。第三类是量纲不统一AQI 是 0-500 的指数PM2.5 是 μg/m³直接放一起建模会放大数值大的特征。第四类是时间粒度不一致有的数据是小时级有的是日级合并前必须对齐。import pandas as pd import numpy as np import missingno as msno # 读取数据注意编码国内数据常见 gbk df pd.read_csv(air_quality.csv, encodinggbk, parse_dates[datetime]) # 统一列名去掉空格和大小写差异 df.columns [c.strip().lower().replace( , _) for c in df.columns] # 把明显是标记值的异常替换成 NaN df.replace([9999, -999, -1], np.nan, inplaceTrue) # 看缺失分布missingno 的矩阵图比 isnull().sum() 直观 print(df.isnull().sum().sort_values(ascendingFalse)) msno.matrix(df)这段代码的逻辑是先统一列名避免后面df[PM2.5]和df[pm2.5]混用再把传感器标记值转成 NaN让它们进入统一的缺失处理流程最后用 missingno 看缺失是随机的还是成片的。如果某个污染物列缺失超过 40%我一般直接考虑丢弃该列而不是硬填因为填出来的数据会污染模型。2.3 缺失值填充与异常值处理的具体参数缺失值填充没有万能方案要看缺失比例和业务含义。缺失小于 5%用前后向填充或均值填充都行缺失在 5% 到 30% 之间我倾向用同城市同时段的中位数填充因为空气质量有强时段规律缺失超过 30%要么丢列要么用模型预测填充但后者容易引入偏差。# 按城市分组用同时段中位数填充污染物列 pollutants [pm2.5, pm10, so2, no2, co, o3] df[pollutants] df.groupby(city)[pollutants].transform( lambda x: x.fillna(x.median()) ) # 气象列用线性插值因为温度湿度是连续变化的 weather [temperature, humidity, wind_speed, pressure] df[weather] df[weather].interpolate(methodlinear, limit3) # 异常值用 IQR 法识别超过 3 倍四分位距的截断 for col in pollutants: q1, q3 df[col].quantile([0.25, 0.75]) iqr q3 - q1 lower, upper q1 - 3 * iqr, q3 3 * iqr df[col] df[col].clip(lower, upper)groupby(city)是关键因为不同城市的污染基线差异巨大用全国中位数填北京的数据会失真。interpolate的limit3表示最多连续插 3 个点超过就留 NaN防止长段缺失被线性外推成假数据。IQR 用 3 倍而不是常见的 1.5 倍是因为空气质量本身波动大1.5 倍会把真实的重污染事件当异常删掉这属于业务判断不是纯统计问题。3. 特征工程与机器学习建模从时间特征到模型选型3.1 时间特征与滞后特征的构造方法空气质量预测的核心特征是时间。原始数据只有一列 datetime但里面藏着大量信息小时反映早晚高峰星期反映工作日和周末差异月份反映季节供暖。把这些拆出来模型效果通常能提升一截。# 时间特征拆解 df[hour] df[datetime].dt.hour df[weekday] df[datetime].dt.weekday df[month] df[datetime].dt.month df[is_weekend] (df[weekday] 5).astype(int) # 滞后特征用前 1、3、6、12 小时的 PM2.5 预测当前值 for lag in [1, 3, 6, 12]: df[fpm25_lag_{lag}] df.groupby(city)[pm2.5].shift(lag) # 滑动窗口统计 df[pm25_roll_mean_6] df.groupby(city)[pm2.5].transform( lambda x: x.rolling(6, min_periods1).mean() ) df[pm25_roll_std_6] df.groupby(city)[pm2.5].transform( lambda x: x.rolling(6, min_periods1).std() )滞后特征必须按城市分组做shift否则会把 A 城市的数据错位到 B 城市。rolling(6)表示 6 小时窗口min_periods1保证序列开头不会因为窗口不满而全变 NaN。滑动标准差反映的是污染波动剧烈程度重污染过程往往标准差先升高这个特征对预测突变很有用。3.2 模型选型为什么用梯度提升而不是线性回归空气质量预测是典型的非线性回归问题。PM2.5 和气象因子之间不是线性关系比如风速对污染物的稀释效应在低风速区间很弱高风速区间很强。线性回归在这种场景下 R² 通常只有 0.5 左右而梯度提升树能到 0.85 以上。我一般先用HistGradientBoostingRegressor做基线它训练快、支持缺失值、不需要独热编码。如果数据量超过 10 万行再考虑 LightGBM。随机森林也能用但预测精度通常比梯度提升低 3 到 5 个百分点而且模型文件更大。from sklearn.model_selection import train_test_split from sklearn.ensemble import HistGradientBoostingRegressor from sklearn.metrics import mean_absolute_error, r2_score # 特征列去掉目标泄漏列和原始时间列 feature_cols [c for c in df.columns if c not in [pm2.5, datetime, aqi]] X df[feature_cols] y df[pm2.5] # 按时间顺序切分不能随机切否则未来数据泄漏到训练集 split_idx int(len(df) * 0.8) X_train, X_test X.iloc[:split_idx], X.iloc[split_idx:] y_train, y_test y.iloc[:split_idx], y.iloc[split_idx:] model HistGradientBoostingRegressor( max_iter300, learning_rate0.05, max_depth6, early_stoppingTrue, validation_fraction0.1, random_state42 ) model.fit(X_train, y_train) pred model.predict(X_test) print(MAE:, mean_absolute_error(y_test, pred)) print(R2:, r2_score(y_test, pred))max_iter300配合early_stoppingTrue模型会在验证集不再提升时自动停避免过拟合。learning_rate0.05是偏保守的学习率配合 300 轮迭代通常够用如果 R² 不理想可以调到 0.1 但要把 max_iter 降到 150 左右。按时间顺序切分是血泪经验随机切分会让模型看到未来测试集 R² 虚高上线就崩。3.3 特征重要性与模型可解释性模型跑通只是第一步能解释才敢用。梯度提升树自带feature_importances_但更可靠的是 permutation importance它不依赖模型内部结构。from sklearn.inspection import permutation_importance result permutation_importance( model, X_test, y_test, n_repeats10, random_state42, n_jobs-1 ) importance_df pd.DataFrame({ feature: feature_cols, importance: result.importances_mean }).sort_values(importance, ascendingFalse) print(importance_df.head(10))n_repeats10表示每个特征打乱 10 次取平均次数越多越稳但越慢。通常滞后 1 小时的 PM2.5 会排第一其次是滑动均值然后才是气象因子。如果发现某个气象特征重要性异常高要检查是不是数据泄漏比如用了未来时刻的温度。4. 可视化落地用 ECharts 把分析结论讲清楚4.1 时间序列趋势图与污染日历热力图可视化不是把数据画出来就完事而是要让不看代码的人也能秒懂结论。时间序列趋势图适合展示长期变化日历热力图适合展示哪天污染重这种模式。from pyecharts.charts import Line, Calendar, Grid from pyecharts import options as opts # 按日聚合避免小时级数据太密看不清趋势 daily df.groupby(df[datetime].dt.date)[pm2.5].mean().reset_index() daily.columns [date, pm25] line ( Line() .add_xaxis([str(d) for d in daily[date]]) .add_yaxis(PM2.5 日均值, daily[pm25].round(1).tolist(), is_smoothTrue, is_symbol_showFalse) .set_global_opts( title_optsopts.TitleOpts(titlePM2.5 日均浓度趋势), xaxis_optsopts.AxisOpts(name日期), yaxis_optsopts.AxisOpts(nameμg/m³), datazoom_opts[opts.DataZoomOpts(range_start0, range_end100)] ) ) line.render(pm25_trend.html)is_smoothTrue让折线平滑但要注意平滑会掩盖极端值如果重点是看峰值就别开。DataZoomOpts加上后可以在浏览器里拖动缩放这对长时间序列很实用。日历热力图用Calendar组件把每天的值映射成颜色深浅一眼就能看出冬季供暖期的污染聚集。4.2 相关性热力图与模型预测对比图相关性热力图用来验证特征工程是否合理预测对比图用来展示模型效果。这两张图放在报告里比一堆数字有说服力。from pyecharts.charts import HeatMap import numpy as np # 计算污染物和气象因子的相关系数 corr_cols [pm2.5, pm10, so2, no2, co, o3, temperature, humidity, wind_speed, pressure] corr_matrix df[corr_cols].corr().round(2) data [] for i, row in enumerate(corr_cols): for j, col in enumerate(corr_cols): data.append([i, j, corr_matrix.loc[row, col]]) heatmap ( HeatMap() .add_xaxis(corr_cols) .add_yaxis(, corr_cols, data, label_optsopts.LabelOpts(is_showTrue, positioninside)) .set_global_opts( title_optsopts.TitleOpts(title污染物与气象因子相关性), visualmap_optsopts.VisualMapOpts(min_-1, max_1, is_calculableTrue, pos_bottom5%) ) ) heatmap.render(correlation.html)visualmap_opts的min_-1, max_1是相关系数的固定范围不要根据数据自动调整否则不同图之间没法对比。如果发现 PM2.5 和 PM10 相关系数超过 0.9说明两者高度共线建模时可以只保留一个或者用 PCA 降维。5. 避坑与排查空气质量数据挖掘最常见的 5 个翻车点5.1 缺失值填充后模型指标虚高现象填充完缺失值模型 R² 从 0.7 跳到 0.95但预测新数据时误差巨大。原因用了全局均值或未来数据填充导致训练集和测试集信息泄漏。比如用整列均值填充测试集的缺失值被训练集的统计量污染。解决填充必须按时间顺序或分组进行测试集的填充参数只能来自训练集。我一般先切分再填充训练集算中位数测试集用训练集的中位数。5.2 时间特征构造时忘记按城市分组现象滞后特征和滑动窗口算出来模型效果反而比不加还差。原因shift和rolling没有groupby(city)导致 A 城市的最后一条数据滑到了 B 城市的第一条特征完全错位。解决所有涉及时间顺序的操作只要数据里有多个城市或多个站点必须分组。检查方法是看分组后每个城市的第一行滞后特征是否为 NaN。5.3 随机切分导致测试集泄漏现象交叉验证 R² 很高但按时间顺序留出的测试集 R² 低很多。原因train_test_split默认随机打乱未来时刻的数据进了训练集模型偷看了答案。解决时间序列必须按时间切分用iloc[:split_idx]和iloc[split_idx:]。如果数据有多个城市还要保证每个城市的切分点一致。5.4 异常值处理把重污染事件删了现象清洗后数据很干净但模型完全预测不出重污染过程。原因IQR 用 1.5 倍系数把 PM2.5 超过 150 的真实重污染值当异常截断了。解决空气质量数据的异常值判断要结合业务用 3 倍 IQR 或直接保留只处理负值和 9999 这类标记值。重污染事件恰恰是预测的重点不能删。5.5 ECharts 图表在浏览器打不开或空白现象render生成的 HTML 打开后一片空白或者图表不显示。原因pyecharts 2.x 默认从 CDN 加载 echarts.min.js内网或断网环境加载失败。另外如果数据里有 NaNJSON 序列化会失败。解决用CurrentConfig.ONLINE_HOST改成离线资源或者把 echarts.min.js 下载到本地。数据里的 NaN 在传给图表前用fillna(0)或dropna()处理掉。6. 把模型装进 Flask 接口一个能演示的最小闭环做到这一步分析和可视化都有了但答辩或演示时评委更想看到输入一组数据系统给出预测的交互。用 Flask 包一个预测接口前端用 ECharts 展示结果整个项目就从脚本升级成了系统。from flask import Flask, request, jsonify import joblib import pandas as pd app Flask(__name__) model joblib.load(air_quality_model.pkl) feature_cols joblib.load(feature_cols.pkl) app.route(/predict, methods[POST]) def predict(): data request.get_json() # 构造单行 DataFrame列顺序必须和训练时一致 row pd.DataFrame([data])[feature_cols] pred model.predict(row)[0] return jsonify({ pm25_pred: round(float(pred), 2), level: 优 if pred 35 else 良 if pred 75 else 污染 }) if __name__ __main__: app.run(host0.0.0.0, port5000, debugFalse)这里的关键是feature_cols要单独保存预测时按同样顺序取列否则 sklearn 会报特征数量不匹配。debugFalse在生产环境必须关否则会暴露源码。前端用fetch调这个接口把返回的 PM2.5 预测值和等级用 ECharts 仪表盘展示整个演示闭环就完成了。模型保存用joblib.dump(model, air_quality_model.pkl)比 pickle 快且对 numpy 数组更友好。如果要部署到服务器用 gunicorn 起多进程gunicorn -w 4 -b 0.0.0.0:5000 app:app-w 4表示 4 个 worker按 CPU 核数调整。我自己的习惯是每次改完特征工程或模型参数先把 MAE 和 R² 记在一个表格里对比着看。有次调了半天参数R² 只涨了 0.01回头一看是某个滞后特征分组写错了修正后直接涨了 0.08。这种教训比任何教程都深刻。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

YOLO全系实战:2000张课堂行为检测数据集训练与避坑指南 2026/9/28 2:46:48

YOLO全系实战:2000张课堂行为检测数据集训练与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
深度学习口罩检测系统:从YOLOv8训练到ONNX部署的实战指南 2026/9/28 2:46:48

深度学习口罩检测系统:从YOLOv8训练到ONNX部署的实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
LTspice网络标签与端口实战:层次化设计提升仿真效率 2026/9/28 2:46:42

LTspice网络标签与端口实战:层次化设计提升仿真效率

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Yao SUI 数据绑定(Data Binding)完全指南:内置变量、JSON 数据配置与后端脚本调用 2026/9/28 2:46:42

Yao SUI 数据绑定(Data Binding)完全指南:内置变量、JSON 数据配置与后端脚本调用

Agent 框架后端低代码RAG 【免费下载链接】yao ✨ All your agents and workspaces in one place, on every device you own. Track tasks on a board, accessible from desktop, mobile, browser, or API. Self-hosted. 项目地址: https://gitcode.com/gh_mirrors/…

阅读更多 →
NoneBot 2 数据库实战:nonebot-plugin-orm 用户指南与迁移 CLI 完全解析 2026/9/28 2:46:42

NoneBot 2 数据库实战:nonebot-plugin-orm 用户指南与迁移 CLI 完全解析

后端即时通讯 【免费下载链接】nonebot2 跨平台 Python 异步聊天机器人框架 / Asynchronous multi-platform chatbot framework written in Python 项目地址: https://gitcode.com/gh_mirrors/no/nonebot2 点击查看 免费下载 nonebot-plugin-orm 是 NoneBot 的官方…

阅读更多 →
Keil5自定义FLM文件:从原理到实战解决Flash烧录失败 2026/9/28 2:46:42

Keil5自定义FLM文件:从原理到实战解决Flash烧录失败

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉