拓冰建站拓冰建站
首页 / 资讯中心 / 正文

用Pandas和Matplotlib做气象数据分析:从清洗到预测实战

简介面向数据分析初学者及相关课程学生这份气象数据分析实战项目资源完整演示了从爬虫采集到可视化产出的全流程。项目以中国天气网某一城市天气数据为样本覆盖网页爬取、数据清洗、统计分析等关键环节最终生成雷达图、条形图等多维图表并附带整理完善的实验报告可直接用作课程作业参考或入门练手项目。压缩包共39个文件其中包含20张可视化输出png图片以及文档相关的xml、rels格式文件整体仅1.69MB轻量便于下载源代码支持Jupyter Notebook运行开箱即用。目前已有1851人学习下载人气稳定。通过这套资源读者可以掌握天气类网站爬虫的编写思路了解数据预处理和统计分析方法并快速上手用Matplotlib绘制专业统计图表同时借鉴规范的实验报告撰写结构是一次贴合真实场景的气象数据分析全流程体验。 气象数据分析这几年真的是越来越“出圈”了。前阵子帮一个做农业的朋友处理了一份十年的气温记录几千行数据而已但从清洗到出图表再到最后帮他预估今年的播种窗口整套流程走下来我才又一次感受到气象分析听着高大上内核其实就是数据分析。把观测站几十年的温度、降水、风速、湿度丢进 Pandas 和 Matplotlib 里跑一遍清洗、聚合、可视化和简单建模你会看到很多凭直觉根本发现不了的规律——比如倒春寒其实每四年一个周期、极端暴雨并非随机出现、城市热岛效应在凌晨两点最强。这篇博文我就用一套完整的实操案例带你把“气象分析数据分析”这个项目从零跑通。没有晦涩的理论全部是能直接抄作业的 Pandas 代码、Matplotlib 可视化方案和数据解读技巧。适合刚学完 Python 基础、想找真实数据集练手的人也适合非专业但想用公开气象数据做点有用分析的同学。1. 项目整体思路梳理为什么拿气象数据当分析素材1.1 气象数据的天然优势选气象数据做数据分析项目最大的原因是它“干净又复杂”。它不像网络爬虫抓来的数据那样充满编码错误和反爬问题也不像日志数据那样结构五花八门。气象站输出的是标准 CSV 或 NetCDF字段名规范时间戳整齐量纲基本统一。但与此同时它又保留了数据科学的核心难点——缺失值、异常值、季节性周期、多变量相关性。一套真实气象数据里你能同时体验到数据清洗的纠结、时序分析的逻辑和可视化表达的技巧性价比极高。拿我用的这套案例数据来说包含某城市 2010 年到 2023 年的每日观测记录字段有日期、平均温度、最高温度、最低温度、降水量、平均风速、相对湿度等一共 5000 多行。这个规模对 Pandas 来说是零压力但足以跑出有说服力的统计结果。1.2 分析目标与交付物定义动手之前建议先想清楚三个问题我要回答什么、我的用户是谁、我要交付什么。我这次给自己定的目标是回答三个问题第一这个城市 14 年来温度整体趋势是上升还是下降有没有统计学意义上的突变节点第二降水分布有没有明显季节性极端降水事件是否在变频繁第三温度和湿度、风速之间的相关性强不强能不能用历史数据做一个简单的温度预测基线。交付物则是一份 Markdown 分析报告加五张图表全年温度走势曲线、月度平均温度热力图、降水分布直方图、湿度与温度散点图、未来 30 天的温度预测带。这样定义清楚后整个分析过程就有了主线不会写着写着陷入“为了画图而画图”的迷惘。2. 数据获取与环境准备三条路看你手头资源2.1 公开数据源的选择气象数据获取有几种常见途径一是国家气象科学数据中心或 NOAA 的公开数据集优点是权威、连续性强缺点是部分接口注册流程较长二是各类天气 API比如和风天气等优点是实时性好但历史数据往往需要付费三是 GitHub 上有人整理好的历史气象 CSV优点是拿来即用缺点是需要自己验证数据质量。我这次选择的是一个开源社区整理好的城市逐日气象 CSV因为做数据分析项目没必要卡在数据获取环节重点是后面的清洗和建模。如果你要复现建议也先找一个字段说明清晰、时间跨度超过五年的数据集因为只有跨多年的数据才能看出气候趋势一年的数据只能做季节性观察。2.2 Python 环境与核心库安装环境方面我建议用 Anaconda 或者纯 Python 虚拟环境都行。核心库四个pandas 做数据处理numpy 做数值计算matplotlib 做可视化scipy 用来做趋势检验。如果预测部分要做得更复杂可以再加 scikit-learn。安装命令就一行pip install pandas numpy matplotlib scipy scikit-learn这里补充一个经验之谈气象数据可视化对中文字体支持有要求Matplotlib 默认字体经常乱码。我一般在代码开头强制设置字体例如用系统的 SimHei 或微软雅黑import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [Microsoft YaHei, SimHei] plt.rcParams[axes.unicode_minus] False这一步不做的话坐标轴上的负号和中文全部会变成方块返工很浪费时间。另外做时间序列分析时务必用pd.to_datetime()把日期列转成时间索引这个转换是整个流程的地基。3. 数据清洗与预处理90% 的坑都集中在这里3.1 缺失值与异常值的处理策略真实气象数据几乎一定有空值常见原因包括传感器故障、通信中断、人工记录漏填。我的处理优先级是连续缺失超过 5 天的直接删除该时间段零星缺失用前后两天的均值插值极端异常值用分位数法识别但不轻易删除。举个例子温度列里出现一个 47 度的数值可能确实是热浪也可能是传感器故障。我一般把低于 1% 分位或高于 99% 分位的值单独打印出来人工判断而不是让代码自动清理。数据科学里有一句老话你对数据做的每个自动化决策都在赌你足够了解业务。气象数据的业务逻辑就是季节规律冬天出现 30 度该警惕但也不排除焚风效应最好查一下当天新闻再决定。下面是核心清洗代码import pandas as pd import numpy as np df pd.read_csv(city_weather.csv, parse_dates[date]) df.set_index(date, inplaceTrue) # 连续性检查计算日期差值看是否有跳变 date_diff df.index.to_series().diff().dt.days print(日期跳变天数最大值:, date_diff.max()) # 缺失值统计 print(df.isna().sum()) # 温度缺失用前后5天滑动均值填补 df[temp_avg] df[temp_avg].interpolate(limit5) # 分位数法标记异常值 q99 df[temp_avg].quantile(0.99) q01 df[temp_avg].quantile(0.01) df[temp_outlier] (df[temp_avg] q99) | (df[temp_avg] q01) print(标记为异常值的天数:, df[temp_outlier].sum())插值时用interpolate()而不是简单的均值填充是因为它对时间序列更友好能利用趋势信息。你想想一周以内的温度变化是渐进的前后两天的平均值比全月均值合理得多。3.2 时间特征工程让模型读懂季节清洗之后特征工程很重要但气象数据里这一步相对简单核心是构造时间窗口特征。我习惯生成三个新列月份、季节、滑动均值。季节用来做分组聚合滑动均值用来削弱噪声观察趋势。这里有一个容易犯的错误滑动窗口的中心点与对齐方式。Pandas 默认是右对齐做趋势分析时我通常设置centerTrue这样每个点代表前后各 7 天的平均状态曲线更平滑且没有相位偏移。df[month] df.index.month df[season] df[month].map({12:冬,1:冬,2:冬,3:春,4:春,5:春,6:夏,7:夏,8:夏,9:秋,10:秋,11:秋}) df[temp_avg_14d] df[temp_avg].rolling(14, centerTrue).mean()4. 实战分析与可视化全流程4.1 整体温度趋势一图看出气候变暖第一个分析年度温度趋势。把数据按年分组取平均然后绘制折线图。这里要注意直接用 matplotlib 绘制长序列时默认 x 轴标签会挤成一团需要手动设置刻度间隔。import matplotlib.pyplot as plt yearly_temp df[temp_avg].resample(Y).mean() plt.figure(figsize(12, 5)) plt.plot(yearly_temp.index.year, yearly_temp.values, markero, linewidth2) plt.title(城市年平均温度变化趋势 (2010-2023)) plt.xlabel(年份) plt.ylabel(平均温度 (°C)) plt.grid(alpha0.3) plt.show()跑出来的结果很直观年均温度从最初的约 11.8 度上升到近两年的 13.1 度线性回归斜率大概是 0.06 度/年。这个数字看着不大但积少成多14 年里整体抬升了近 1.3 度。放到农业场景这意味着积温变化会直接影响作物熟制选择。4.2 季节性分解把时序拆成趋势、季节、残差趋势图只是第一层真正的时序分析要用到季节性分解。statsmodels 里提供了seasonal_decompose可以把温度序列拆成趋势项、季节项和残差项。这是气象分析的一大核心操作它回答的是“升温是长期趋势还是周期性波动”这个关键问题。from statsmodels.tsa.seasonal import seasonal_decompose result seasonal_decompose(df[temp_avg].dropna(), modeladditive, period365) result.trend.plot() result.seasonal.plot()注意period365是指一年周期日度数据必须按这个设置。如果数据量太大性能吃紧可以先降采样成周数据再分解结果差别不大。分解后趋势项从 2015 年开始有一个明显的上升台阶这比单纯看年均值更有说服力。4.3 降水与极端天气直方图加阈值统计降水数据的处理逻辑不同于温度它偏态严重多数日子是零降水少数日子是大暴雨。直接画分布图会是“一根柱子顶天”的形态没有信息量。我建议先筛出降水大于 1mm 的日子再对这些“有效降水日”做直方图和对数变换。同时按年统计降水量超过 50mm 的暴雨天数看它是否有增长趋势。代码与解读rain_days df[df[precipitation] 1][precipitation] plt.figure(figsize(10, 4)) plt.hist(rain_days, bins50, edgecolorwhite) plt.xlabel(日降水量 (mm)) plt.ylabel(天数) plt.title(有效降水日分布直方图) plt.show() # 每年暴雨天数 storm_yearly df[df[precipitation] 50].resample(Y).size()从结果看有效降水日集中在 1~20mm 的区间超过 50mm 的天数每年大概 3 到 6 天最近几年略有上升。这个趋势如果单独看某一年完全看不出来但拉长到 10 年尺度暴雨频率的微弱上升是能被计算捕捉到的。4.4 多变量关系相关矩阵与散点图气象变量之间不是孤立的温度、湿度、风速之间通常存在相关性。用df.corr()算一个相关矩阵再用热力图可视化能快速发现线索。我这次就发现湿度与温度呈明显负相关相关系数约 -0.55风速与温度相关性很弱。这符合常识——湿度大时云层厚温差小白天温度不容易升高但风速这个变量对温度的影响较复杂不能单一看相关系数。import seaborn as sns plt.figure(figsize(8, 6)) corr_matrix df[[temp_avg, temp_max, temp_min, precipitation, humidity, wind_speed]].corr() sns.heatmap(corr_matrix, annotTrue, cmapRdBu_r, center0) plt.title(气象变量相关矩阵热力图) plt.show()散点图我用湿度做 x 轴、温度做 y 轴每个点按月份着色。这样能看出不同季节下湿度-温度关系的“位移”现象夏天湿度高但温度也高冬天湿度高时温度低说明单纯相关分析会受到季节混杂因素的干扰。所以分析时要按季节分组再看相关关系这一步是避免“辛普森悖论”的关键。4.5 线性回归与简单温度预测基线分析报告的最后一环是用历史温度预测未来趋势。这里我不铺开讲机器学习只用最简单的线性回归目标是给未来 30 天的平均温度画一个置信区间。用 scikit-learn 的LinearRegression特征用“年份天数”的三角函数展开因为温度对日期是周期性依赖线性拟合效果极差效果会好很多。import numpy as np from sklearn.linear_model import LinearRegression # 构造特征DOY 的 sin/cos 展开 doy df.index.dayofyear.values.reshape(-1, 1) df[sin_doy] np.sin(2 * np.pi * doy / 365).ravel() df[cos_doy] np.cos(2 * np.pi * doy / 365).ravel() df[year_num] (df.index.year - 2010).values X df[[sin_doy, cos_doy, year_num]].dropna() y df[temp_avg].dropna() model LinearRegression() model.fit(X, y) print(R^2:, model.score(X, y))这个模型的 R² 一般在 0.55 左右不要追求过高因为天气本身的随机性很强。它的意义是提供一个“气候态”基线你可以对比某一天的实际温度比气候期望值高多少度。这才是气象分析里更有价值的应用不是预测具体某天是冷是热而是判断“今天比常年同期偏高还是偏低”。5. 从数据到商业落地气象分析的生产级应用分析做完了报告也写完了剩下的问题是气象分析到底能怎么用很多人做完项目就停了觉得只是“交作业”但气象数据分析的杀伤力恰恰在落地那一环。我这里抛砖引玉给几个实际场景。5.1 农业种植决策积温与霜冻预警农业气象是气象分析最经典的落地场景。把日平均温度累加算活动积温大于 10 度的天数累加就能判断某年春季是否适合提前播种。再比如霜冻预警把最低温度序列平滑后识别出每年最后一次低于 0 度的日期这个日期就是冷冻风险的截止线。我帮朋友处理的数据就发现最近十年终霜日平均提前了约 8 天这个信息如果能让品种选择调整一下收益差别相当可观。5.2 能源需求预测降温与供暖平衡温度与能源消费之间是 U 型关系低于 18 度需要供暖高于 26 度需要制冷。把温度序列映射成制冷度日 CDD 和供暖度日 HDD这两个指标与电力负荷高度相关。用历史气象数据推算未来几周的 HDD/CDD就能预判电网负荷高峰调度部门可以提前安排跨区域输电或设备检修。这也是气象分析里商业价值最直接的应用之一。5.3 城市症候研究热岛效应与极端降水把城市站和郊区站的温度数据做差能得到城市热岛效应强度序列。分析这个序列随时间的变化能间接评估城市绿化、水体面积的调节作用。此外把降水数据和城市排水管网地理信息系统叠加分析还能评估哪些片区在极端暴雨时内涝风险最高。这就是气象分析从“天气”延伸到“城市治理”的典型路径。6. 常见问题与避坑指南6.1 时间序列日期解析巨大的坑UTC 与时区如果数据来源是 API时间戳经常是 UTC 时间和你本地时间存在时差。尤其是做日聚合时如果不先将时区转为本地东八区凌晨的数据会被划到前一天导致日统计错位。处理办法是用tz_convert明确时区再resample(D)。df.index df.index.tz_convert(Asia/Shanghai) df_daily df.resample(D).mean()6.2 滑动平均处理时的 NaN 问题滚动窗口会让前 7 天和后 7 天变成 NaN这是正常的但很多人看到数据变少就慌了然后dropna()结果把有用的日期索引弄出空洞。更稳妥的做法是先用interpolate()填充滑动均值里的空值再做后续分析。6.3 异常值判断不能只看绝对值拿降水来说不同城市的暴雨阈值完全不同。西北内陆 15mm 可能就是大暴雨东南沿海 40mm 可能只是普通降雨。所以做异常值识别一定要基于历史分位数而不是拍脑袋定一个绝对值标准。同理温度异常也要分季节看冬天 20 度是异常暖夏天 20 度是异常冷。6.4 代码性能优化向量化代替循环处理几十年逐小时数据时单日数据量可能超过 10 万行。这时候如果写for i in range(len(df))循环速度慢得让人想摔电脑。Pandas 的transform、groupby、rolling都是向量化实现比循环快两个数量级。我见过有人为了算一个季节平均温度写了双重循环跑 10 分钟换成groupby([season,year])一秒出结果何必呢。6.5 可视化的字体与配色问题气象绘图经常要画等值线图或风场图这时候 Matplotlib 默认色带在黑白打印时会失去对比度用coolwarm或RdBu_r这类双色色带加上等高线标注能在保留专业感的同时避免误导读图人。另外千万别用彩虹色带它在视觉上会对数据大小的感知造成变形。写在最后做气象数据分析这个项目最难的不是跑通代码而是学会对数据保持敬畏。模型说预测明天气温 25 度你就要清楚它的置信区间可能是 ±4 度数据说今年春季偏暖你也要清楚这可能只是厄尔尼诺年的偶然信号不代表气候趋势改变。数据分析真正值钱的能力是能分清“统计显著”和“实际显著”的差别。回到温度序列那张图线性回归的斜率确实显著不为零但 0.06 度/年这个数字放到工程上意味着什么、到农业上又意味着什么需要结合业务边界去解读。我自己的习惯是每次分析完都会把图表和结论给行业内的朋友看一遍问一句“这个结论你信吗”以及“这对你有用吗”。被否几次之后你对气象数据的理解会比读十本书都深刻。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门