数据清洗实战如何处理CN-AIR数据集中的缺失值与异常值完整指南【免费下载链接】CN-AIR项目地址: https://ai.gitcode.com/GewisLab/CN-AIR数据清洗是数据分析中最耗时也最关键的一步。本文将带你实战处理CN-AIR 数据集中的缺失值与异常值——这是一个覆盖 2014 至 2026 年中国 300 城市空气质量的历史数据集实测单文件缺失率最高可达 48.6%异常值更是数以千计。学会下面的数据清洗方法你就能把这份原始数据变成可放心分析、建模的干净数据。CN-AIR 数据集长什么样CN-AIR 是开源的中国空气质量历史数据集数据来源于中国环境监测总站CNEMC按天拆分存储目录结构清晰目录时间范围文件数城市_20140513-20141231/2014年224城市_20150101-20151231/2015年364城市_20240101-20241231/2024年366城市_20250101-20251231/2025年365城市_20260101-20260418/2026年113完整列表见 README.md全部城市级文件共4349 个 CSV仓库约 2.2GB。每个 CSV 是宽表格式首行即表头date,hour,type,北京,天津,石家庄,... 20240101,0,AQI,54,57,85,... 20240101,0,PM2.5,21,25,42,...包含15 种数据类型AQI、PM2.5、PM2.5_24h、PM10、PM10_24h、SO2、NO2、O3、O3_8h、CO 等。读取方式很简单import pandas as pd df pd.read_csv(城市_20240101-20241231/城市_20240101-20241231/china_cities_20240101.csv) print(df.shape) # 输出 (359, 378)378列 ≈ 375个城市 3个标识列缺失值有多严重实测数据告诉你 动手清洗前先用代码摸清缺失值的家底。下面这行命令扫描整个 2024 年数据import pandas as pd, glob files glob.glob(城市_20240101-20241231/城市_20240101-20241231/*.csv) miss 0 for f in files: df pd.read_csv(f) miss df.isna().sum().sum() print(f2024年缺失单元格总数: {miss})实测发现三个规律早期数据缺失率高2014 年首日文件缺失率高达48.6%61545/126615 单元格2015 年已降至 1.0%2024 年单日文件仍有 25899 个缺失主要集中在部分城市站点建设晚、设备维护期缺失无固定模式AQI、PM2.5、SO2 等指标都可能缺需按列逐一处理缺失值处理方法3 招搞定 ️方法一直接删除适用于少量缺失当缺失占比 5% 且不影响统计口径时直接丢弃最省事df_clean df.dropna(subset[AQI]) # 删除AQI缺失的行 df_clean df.dropna(axis1, threshlen(df)*0.9) # 删除缺失超10%的列方法二统计量填充适用于随机缺失用均值、中位数填充是经典做法注意按城市、按指标分组填充更合理df[PM2.5] df.groupby(city)[PM2.5].transform(lambda x: x.fillna(x.median()))方法三时间插值空气质量数据的最优解空气质量是强时间序列相邻小时的数值高度相关用插值还原更自然df[PM10] df[PM10].interpolate(methodlinear, limit_directionboth)异常值检测5 秒扫出全年的离谱数据 ️空气质量数据异常值主要有三种负值、超物理极限值、突变跳变。一条 awk 命令就能全仓扫描awk -F, NR1{for(i4;iNF;i){ if($i!$i00)neg; if($3AQI$i!$i0500)aqi; if(($3PM2.5||$3PM10)$i!$i01000)pm}} END{print 负值:,neg, AQI500:,aqi, PM1000:,pm} \ 城市_20240101-20241231/城市_20240101-20241231/*.csv实测结果异常类型2024年2025年负值不可能出现00AQI 500超爆表值00PM2.5/PM10 1000 μg/m³25082966PM 超 1000 的记录大多来自沙尘暴、春节燃放等极端天气属于真异常需要单独甄别而非直接删除。异常值处理保留真实还是标记剔除⚖️负值物理上不可能直接置为 NaN 后走缺失值流程超限值PM1000先与新闻、气象记录比对。若对应沙尘暴日期属真实极端事件建议保留并单独标记防止影响整体统计突变跳变1小时内 PM2.5 从 50 跳到 500用滚动窗口 Z-Score 检测df[zscore] (df[PM2.5] - df[PM2.5].rolling(24).mean()) / df[PM2.5].rolling(24).std() df.loc[df[zscore].abs() 5, PM2.5] None # 标记为缺失再走插值完整数据清洗流水线一步到位 把上面所有步骤串起来就是一份可直接复用的数据清洗模板import pandas as pd, glob def clean_file(path): df pd.read_csv(path) df df.melt(id_vars[date,hour,type], var_namecity, value_namevalue) # 1. 负值 → NaN df.loc[df[value] 0, value] None # 2. 超物理极限 → NaNCO单位mg/m³上限可放宽 df.loc[(df[type].isin([PM2.5,PM10])) (df[value] 1000), value] None # 3. 按城市指标分组中位数填充 df[value] df.groupby([city,type])[value].transform( lambda x: x.fillna(x.median())) return df dfs [clean_file(f) for f in glob.glob(城市_2024*/城市_2024*/*.csv)] combined pd.concat(dfs, ignore_indexTrue) combined.to_parquet(china_cities_clean.parquet, enginepyarrow)清洗后导出 Parquet 格式读取速度比 CSV 快 5~10 倍后续分析事半功倍。数据清洗检查清单 ✅读取后用df.info()查看各列缺失数量与数据类型检查date、hour、type是否有重复组合实测本数据集无重复扫描负值与超物理极限值AQI 范围 0-500PM 一般 1000缺失率 40% 的早期数据建议直接排除或仅作趋势参考清洗前后各存一份保留原始数据备份记录清洗日志删了多少、填了多少、阈值依据保证可复现结语处理CN-AIR 数据集的缺失值与异常值并没有想象中复杂先扫描、再分类、后处理三步即可得到干净可靠的空气质量数据。真实的缺失率最高 48.6%和异常值规模每年超 2000 条也提醒我们任何公开数据集都不能拿来即用数据清洗永远是分析的第一道工序。动手实践吧用上面的模板处理 2014 与 2024 两年的数据你会直观感受到清洗前后分析结果的巨大差异【免费下载链接】CN-AIR项目地址: https://ai.gitcode.com/GewisLab/CN-AIR创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考