ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python空气污染数据可视化大作业:从数据清洗到报告答辩全流程

Python空气污染数据可视化大作业:从数据清洗到报告答辩全流程 简介这份资源是面向高校学生与Python初学者的数据分析可视化课程设计完整方案以空气污染数据为分析对象涵盖数据清洗、统计分析与交互式可视化全流程适合用作期末大作业、课程设计或数据分析入门练手项目。压缩包共288个文件约104.33MB包含12个py源码文件、15个ipynb分析笔记、42个csv数据文件、34个html页面及配套css、js资源另有pdf报告、pptx答辩演示与mp4演示视频代码注释完整部署后即可运行。目前已有1065人学习下载。项目功能完善、界面美观读者可获得可直接提交的满分大作业源码与报告并借助notebook逐步理解数据处理与图表绘制思路快速掌握Python数据分析可视化的核心方法。1. 空气污染数据可视化系统一份大作业怎么做到能讲清、能跑通、能拿高分每年到期末问得最多的就是「Python数据分析可视化大作业做什么方向不容易翻车」。空气污染数据可视化分析系统是其中性价比很高的选题数据公开、指标清晰、图表类型丰富还能自然带出数据清洗、时间序列、地理分布这几条主线答辩时老师随便追问一句「你这个 AQI 怎么算的」你都能接住。它本质上是一套「采集或读取空气质量数据 → 清洗对齐 → 多维统计 → 可视化呈现 → 报告输出」的完整链路适合数据分析、可视化、Python入门这几类课程的大作业也适合想拿它当第一个数据分析项目练手的人。这篇笔记按我实际带学生做这类项目的顺序拆开讲数据从哪来、代码怎么写、图表怎么选、报告怎么组织、哪些地方最容易翻车。目标很直接——你照着走一遍能交出一份自己讲得明白、老师挑不出硬伤的作业。2. 数据从哪来、字段怎么定先把地基打对2.1 空气污染数据的三种常见来源与取舍做空气污染可视化第一步不是写代码是确定数据。常见来源有三类各有各的坑。第一类是公开空气质量平台的历史数据接口能拿到逐小时的 PM2.5、PM10、SO2、NO2、CO、O3 六项污染物浓度以及 AQI 和首要污染物。优点是字段规范、时间连续缺点是接口有调用频率限制批量拉取要控制节奏。第二类是各地环保部门公开的年度或月度统计报表通常是 Excel 或 CSV优点是权威、适合做宏观趋势缺点是颗粒度粗很多只有月均值做不了小时级波动分析。第三类是自己用爬虫抓的实时页面数据优点是能体现「数据获取」这一环缺点是页面结构一变就失效而且实时数据量小做不出有说服力的趋势图。我的建议是主数据用第一类或第二类保证有足够长的时间跨度至少一年最好两到三年爬虫作为补充或干脆不用。大作业的核心是分析和可视化不是爬虫稳定性把精力压在爬虫上属于本末倒置。如果老师明确要求体现数据获取能力那就用爬虫抓一份小样本再和公开数据集合并报告里说明两部分来源即可。字段方面一份能支撑完整分析的空气污染数据集至少要有这几列城市名、监测时间精确到小时或天、AQI、PM2.5、PM10、SO2、NO2、CO、O3、首要污染物。如果要做地理分布再加经纬度要做城市对比城市名要统一别出现「北京」和「北京市」混用。2.2 用 pandas 读数据并做第一轮体检拿到数据后别急着画图先做体检。下面这段代码是我每次开新数据集都会跑的用来快速看清数据长什么样、缺多少、有没有明显异常。import pandas as pd import numpy as np # 读取数据注意编码国内公开数据常见 gbk 或 utf-8-sig df pd.read_csv(air_quality.csv, encodingutf-8-sig) # 统一列名去掉前后空格避免后面按列名取值时报 KeyError df.columns [c.strip() for c in df.columns] # 时间列转成 datetime后续做时间序列必须走这一步 df[监测时间] pd.to_datetime(df[监测时间], errorscoerce) # 第一轮体检形状、类型、缺失、描述统计 print(数据形状:, df.shape) print(df.dtypes) print(缺失值统计:\n, df.isnull().sum()) print(数值列描述统计:\n, df.describe()) # 看时间范围确认跨度够不够做趋势 print(时间范围:, df[监测时间].min(), 到, df[监测时间].max()) # 看城市数量确认对比维度 print(城市数量:, df[城市名].nunique())这段代码的逻辑是先解决编码和列名这两个最常见的读取问题再把时间列转成 datetime不转的话后面按时间分组、重采样全做不了然后用 shape、dtypes、isnull、describe 四个输出快速判断数据质量。参数上errorscoerce会把无法解析的时间变成 NaT方便你一眼看出有多少脏时间encoding要根据实际文件调整读出来乱码就换gbk或gb18030。体检完你会遇到几种典型情况缺失值集中在某几个污染物列、时间有重复、AQI 出现 0 或 500 这种边界值。这些都要在清洗阶段处理别带着脏数据往下走否则后面图表会出现莫名其妙的断点或尖刺。2.3 清洗与对齐缺失值、异常值、时间重采样清洗这一步决定了后面图表可不可信。我的处理顺序是先去重再处理异常值再补缺失最后按需要重采样。# 1. 按城市时间去重保留第一条 df df.drop_duplicates(subset[城市名, 监测时间], keepfirst) # 2. 异常值处理AQI 合理范围 0-500污染物浓度不能为负 df.loc[(df[AQI] 0) | (df[AQI] 500), AQI] np.nan for col in [PM2.5, PM10, SO2, NO2, CO, O3]: df.loc[df[col] 0, col] np.nan # 3. 缺失值按城市分组做时间插值比全局均值填充合理得多 df df.sort_values([城市名, 监测时间]) df[PM2.5] df.groupby(城市名)[PM2.5].transform( lambda s: s.interpolate(methodlinear, limit3) ) # 4. 重采样把小时数据聚合成日均减少噪声便于画趋势 df_daily ( df.set_index(监测时间) .groupby(城市名) .resample(D)[[AQI, PM2.5, PM10, SO2, NO2, CO, O3]] .mean() .reset_index() )逻辑说明去重防止同一时间点重复计数异常值置为 NaN 而不是直接删行是为了保留其他列的有效信息插值用groupby按城市分别做避免用 A 城市的均值去填 B 城市的空缺limit3限制最多连续补三个点补太多就是编数据了重采样成日均是为了让趋势图更干净小时级波动留到专门的分析里看。参数上resample(D)里的 D 可以换成W周、M月看你想讲什么粒度的故事。提示插值只适合连续缺失较少的场景。如果某个城市某段时间整段缺失插值会造出假数据这种情况应该在报告里说明并剔除该时段而不是硬补。3. 可视化怎么做从单指标趋势到多维对比3.1 用 matplotlib 画一张能进报告的 AQI 趋势图趋势图是空气污染可视化的基本盘。很多人画出来的图能用但不好看问题通常出在默认样式、中文乱码、时间轴拥挤这三处。下面这段代码把这三个问题一起解决。import matplotlib.pyplot as plt import matplotlib.dates as mdates # 中文字体设置Windows 用 SimHeiMac 用 Arial Unicode MS plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 解决负号显示为方块 fig, ax plt.subplots(figsize(12, 5)) # 取一个城市画 AQI 日均趋势 city 北京 sub df_daily[df_daily[城市名] city] ax.plot(sub[监测时间], sub[AQI], color#2c7fb8, linewidth1.5, labelAQI) # 加一条 100 的参考线AQI 超过 100 即轻度污染 ax.axhline(y100, color#e34a33, linestyle--, linewidth1, label轻度污染阈值) # 时间轴格式化避免标签重叠 ax.xaxis.set_major_locator(mdates.MonthLocator(interval2)) ax.xaxis.set_major_formatter(mdates.DateFormatter(%Y-%m)) ax.set_title(f{city} AQI 日均变化趋势, fontsize14) ax.set_xlabel(时间) ax.set_ylabel(AQI) ax.legend() plt.tight_layout() plt.savefig(aqi_trend.png, dpi150) plt.show()逻辑说明先设字体和负号这是中文图表必做的一步不做就是一堆方块figsize控制画布比例12×5 适合放进报告正文参考线用axhline加比在图上手写标注更规范时间轴用MonthLocator控制密度数据跨度一年以上时特别重要。参数上dpi150是报告插图比较清晰的档位再高文件会很大颜色用十六进制而不是red、blue是为了让整份报告的配色统一。这张图能讲的故事季节性波动冬季取暖期 AQI 明显升高、异常峰值某几天突然飙高可以结合沙尘或静稳天气解释、整体趋势逐年改善还是恶化。报告里不要只贴图每张图下面配两三句解读这是拉开分数的地方。3.2 多城市对比分组柱状图和箱线图怎么选单城市趋势讲完自然要横向对比。对比图有两种常见选择用途不同。分组柱状图适合比较各城市在某个统计量上的差异比如年均 AQI、各污染物年均浓度。箱线图适合看分布和离散程度能一眼看出哪个城市波动大、哪个城市有极端值。我的经验是讲「谁高谁低」用柱状图讲「谁稳定谁波动」用箱线图两个都放报告的分析层次就出来了。# 各城市年均 AQI 对比分组柱状图 annual df_daily.groupby(城市名)[AQI].mean().sort_values(ascendingFalse) fig, ax plt.subplots(figsize(10, 5)) bars ax.bar(annual.index, annual.values, color#41b6c4) ax.set_title(各城市年均 AQI 对比) ax.set_ylabel(年均 AQI) # 在柱顶标数值方便直接读数 for bar in bars: height bar.get_height() ax.text(bar.get_x() bar.get_width() / 2, height, f{height:.1f}, hacenter, vabottom, fontsize9) plt.tight_layout() plt.savefig(city_compare.png, dpi150) plt.show() # 各城市 AQI 分布对比箱线图 fig, ax plt.subplots(figsize(10, 5)) df_daily.boxplot(columnAQI, by城市名, axax, gridFalse) ax.set_title(各城市 AQI 分布对比) ax.set_xlabel(城市) ax.set_ylabel(AQI) plt.suptitle() # 去掉 pandas 默认的副标题 plt.tight_layout() plt.savefig(aqi_box.png, dpi150) plt.show()逻辑说明柱状图先排序再画读者一眼能看出排名柱顶标数值省去读者对着坐标轴估读的麻烦。箱线图用 pandas 自带的boxplot最快但默认会加一个多余的副标题用plt.suptitle()去掉。参数上gridFalse让图面更干净报告插图不需要网格线。注意箱线图的箱体是四分位距上下须是 1.5 倍四分位距内的极值超出的是离群点。报告里解释箱线图时别把上下须说成最大最小值这是答辩常被追问的点。3.3 污染物相关性热力图把六项指标的关系讲清楚空气污染六项指标之间不是独立的PM2.5 和 PM10 高度相关NO2 和 O3 有复杂的日变化关系。用一张相关性热力图能把这种关系直观呈现出来也是数据分析能力的体现。import seaborn as sns pollutants [AQI, PM2.5, PM10, SO2, NO2, CO, O3] corr df_daily[pollutants].corr() fig, ax plt.subplots(figsize(8, 6)) sns.heatmap(corr, annotTrue, fmt.2f, cmapRdYlBu_r, vmin-1, vmax1, squareTrue, axax) ax.set_title(空气污染物相关性热力图) plt.tight_layout() plt.savefig(corr_heatmap.png, dpi150) plt.show()逻辑说明corr()默认算皮尔逊相关系数适合线性关系annotTrue把数值标在格子里fmt.2f控制两位小数cmapRdYlBu_r是红蓝配色红色正相关、蓝色负相关比默认配色更符合直觉vmin-1, vmax1固定色标范围避免不同图之间颜色不可比。参数上如果数据有明显非线性关系可以改用斯皮尔曼相关系数把corr()换成corr(methodspearman)。这张图能讲的点PM2.5 和 PM10 相关系数通常在 0.8 以上说明颗粒物污染同源O3 和其他污染物常呈负相关因为臭氧在高温强日照下生成和冬季颗粒物污染不同期。报告里把这些解读写出来比单纯贴图强很多。4. 避坑与排查这类大作业最容易翻车的五个地方4.1 中文乱码图里全是方块现象matplotlib 画出来的图标题、坐标轴中文全变成方块或问号。原因matplotlib 默认字体不含中文且负号用的 Unicode 减号也不在默认字体里。解决在画图前设置plt.rcParams[font.sans-serif] [SimHei]Windows或[Arial Unicode MS]Mac同时设plt.rcParams[axes.unicode_minus] False。如果换了环境还是乱码用matplotlib.font_manager查一下系统里到底有哪些中文字体别硬套字体名。4.2 时间列没转 datetime分组全乱现象按时间分组时月份顺序是乱的或者resample直接报错。原因时间列读进来是字符串字符串排序按字典序2023-10会排在2023-2前面。解决读数据后立刻pd.to_datetime并检查有没有解析失败的 NaT。有 NaT 就回头查原始数据的时间格式是否统一别带着 NaT 往下做。4.3 缺失值用全局均值填充城市间差异被抹平现象清洗后各城市数据看起来都差不多对比图没有区分度。原因用全局均值填充等于把污染重的城市往下拉、污染轻的城市往上抬城市间真实差异被平均掉了。解决按城市分组插值或分组填充groupby(城市名)之后再transform。如果某城市缺失太多考虑剔除该城市并在报告里说明而不是硬填。4.4 图表堆砌但没有解读答辩被问住现象报告里十几张图但每张图下面只有「如图所示」四个字。原因把可视化当成了出图任务没当成分析任务。解决每张图配两三句解读说清这张图回答了什么、看到了什么规律、可能的原因是什么。宁可少放两张图也要把留下的图讲透。答辩时老师问的永远是「你为什么这么画」「这个结论怎么来的」不是「你画了几张图」。4.5 代码和报告对不上数据版本混乱现象报告里的数字和代码跑出来的对不上或者换台电脑跑不出同样结果。原因中间改了清洗逻辑但没重跑或者数据文件被覆盖过。解决把清洗、分析、出图拆成独立脚本按顺序跑数据文件只读不改中间结果另存报告里的关键数字直接从脚本输出里复制不手敲。这是工程习惯也是答辩时能自证清白的底气。5. 报告怎么写、项目怎么讲从能跑到能拿分代码跑通只是及格线报告和讲解才是拿高分的地方。我的习惯是把报告按「数据来源与字段说明 → 清洗流程与依据 → 分析维度与图表 → 结论与局限」四段组织每段都对应代码里的一个环节做到报告里的每句话都能在代码里找到出处。数据来源那段写清数据从哪来、时间跨度、字段含义、样本量。清洗那段把缺失率、异常值处理方式、插值方法写出来最好附一张清洗前后的对比表。分析维度那段是主体按单指标趋势、多城市对比、污染物相关性三条线展开每条线配图配解读。结论与局限那段别写空话写具体发现比如「冬季 AQI 显著高于夏季主要受 PM2.5 和 PM10 驱动」再写两条局限比如「数据仅覆盖一年无法判断长期趋势」「未纳入气象因素相关性不等于因果」。答辩讲解有个技巧别按代码顺序讲按「我想回答什么问题 → 用了什么数据和方法 → 看到了什么 → 说明什么」讲。老师关心的是你的分析思路不是你调了哪些库。被问到不会的直接说「这一点我没深入我的理解是……」比硬编强。最后说个我自己的习惯这类项目做完我会把清洗和分析脚本单独抽出来换一份新数据跑一遍看能不能直接复用。能复用说明这套流程是真跑通了不是对着这一份数据凑出来的。这个习惯帮我避开了很多「换数据就崩」的坑也希望帮到你。本文还有配套的精品资源点击获取
返回列表