资讯动态

新疆历史降水量数据可视化分析:从数据清洗到机器学习建模实战

发布时间:2026/9/13 20:25:20 来源:尧图企业网站定制
简介一套基于Python的新疆历史降水量可视化分析资料包面向毕业设计、课程设计及数据挖掘入门者。项目使用Pandas读取并清洗1980—2018年降水数据借助Matplotlib、Seaborn绘制历史趋势折线图、年度总降水量条形图、月度平均降水量饼图等清晰呈现雨季6—8月与旱季10—11月的分布规律同时对比监测站平均降水量并基于ARIMA模型完成月度降水量预测与结果验证。压缩包共4个文件包含Excel数据集、可运行Notebook代码、HTML结果展示页及依赖环境说明txt整体仅5.16MB。Notebook代码按步骤划分包含数据预处理、异常年份识别、年度/月度分析、季节性对比及模型构建与评估等模块注释清晰便于学习者理解每个环节的分析思路和实现方法。目前已有149人学习适合需要快速搭建完整数据分析流程、理解时间序列建模与可视化表达的学生参考。1. 基于大数据的新疆历史降水量数据可视化分析从数据挖掘到机器学习建模的完整落地路径气象数据是典型的海量时序数据新疆作为典型干旱半干旱区其降水数据具有极强的地域特征与稀疏性直接套用通用时间序列模型往往效果惨淡。这个标题看起来是毕业设计实际踩中了数据挖掘完整链路从原始气象站点数据出发经过清洗、降维、特征工程再到机器学习模型构建最后落到可视化大屏呈现几乎覆盖了数据分析从业者的核心日常。本文就是把这条链路拆开给出可复现的数据处理方案、模型选型与调参思路以及基于 ECharts 的企业级数据可视化实现。无论你是正在准备大数据毕业设计还是需要处理区域气象数据做业务分析这些步骤和参数都值得直接抄走。2. 数据获取与数据清洗新疆降水数据的多源整合与异常值处理策略2.1 多源数据获取的常见做法站点数据优先再考虑再分析资料历史降水量数据的来源主要有三类国家气象信息中心的地面气象站点逐日数据、中国区域高分辨率降水融合产品如 CLDAS以及再分析数据集如 ERA5。对于毕设或中小规模分析最可靠的是站点数据——它可以直接落地不需要处理卫星反演和同化系统带来的偏差。新疆范围约 166 万平方公里站点数量约 200 余个对单机分析而言体量不大属于典型的小数据大价值场景不涉及分布式集群部署一台普通开发机即可搞定。我一般会先用爬虫脚本从公开气象数据平台抓取站点信息表再根据经纬度匹配各站点的逐日降水记录。这里要特别注意的是新疆站点稀疏且分布极不均匀天山山区和昆仑山北坡站点密度明显高于盆地后续建模时应将站点空间分布作为重要背景变量引入。import pandas as pd # 假设已抓取原始站点降水数据 df pd.read_csv(xinjiang_precip_raw.csv) # 数据列: station_id, date, precip(mm), lat, lon, elev df[date] pd.to_datetime(df[date]) df df.sort_values([station_id, date]) print(df.shape) print(df.isnull().sum())读取后建议先按站点维度统计空值比例。这里有一个新疆数据常见的坑冬季部分高海拔站点会因为设备冻结而出现连续数日空值不能直接按整站删除否则会破坏时间连续性。空值处理策略我一般分三级连续缺失不超过 3 天用线性插值3 到 10 天用该站同期多年平均值填充超过 10 天直接置为该站历年该日平均值的八成并在数据集中追加标记列方便建模时识别。2.2 异常值识别聚类与四分位距结合的方法降水数据的异常值和一般业务数据不太一样极大的值——比如新疆夏季天山山区单日暴雨——往往不是噪声而恰恰是气候研究的关键对象。直接按 3 倍标准差剔除会把极端降水事件全部删光这在气象分析里是不被接受的。我建议采用 IQR 结合局地聚类的方式来区分真正的仪器错误与极端气候事件。# 按月-站组合计算IQR标记异常候选点 df[year_month] df[date].dt.to_period(M) q1 df.groupby([station_id, year_month])[precip].transform(quantile, 0.25) q3 df.groupby([station_id, year_month])[precip].transform(quantile, 0.75) iqr q3 - q1 df[outlier_candidate] (df[precip] q3 3 * iqr) | (df[precip] q1 - 3 * iqr) # 查看候选异常值分布 candidate df[df[outlier_candidate] True] print(candidate.groupby(station_id).size().sort_values(ascendingFalse))这里倍数取 3 而不是常见的 1.5因为降水数据本身偏态分布尾部天然厚重1.5 倍会误杀大量正常强降水。筛选出候选异常值后再看同一天周边 3 个以上站点是否同时有降雨记录如果有则大概率是真实天气过程保留如果仅单站剧烈偏离再人工核对原始记录确定为设备故障后剔除。这个流程比纯统计阈值合理得多并且中间产物可以直接写入数据挖掘报告作为方法论支撑。2.3 降水数据的重采样与融合从逐日到多时间尺度的特征覆盖降水量分析通常不止看逐日值月尺度、季节尺度、年尺度的统计特征对趋势分析更有价值。重采样时建议同时产出三套数据逐日序列、逐月汇总总量、最大日值、降水日数、连续无降水日数、逐年汇总。这里有个关键点新疆降水集中且季节性强直接用 pandas 的 resample 默认参数会忽略无降水月份的存在导致降水集中度计算失真。# 以某站为例逐月聚合 station df[df[station_id] 51053] monthly station.set_index(date)[precip].resample(M).agg( totalsum, max_dailymax, rainy_dayslambda x: (x 0.1).sum(), dry_dayslambda x: (x 0.1).sum() ) monthly[consecutive_dry_max] station[precip].rolling(30).apply( lambda x: (x 0.1).sum(), rawTrue )这个聚合过程实际上在做数据挖掘里最基础的特征提取工作。rainy_days的阈值取 0.1mm 而不是 0是因为气象观测中微量降水小于 0.1mm通常只记录痕迹不好直接算作有效降水日。后续做机器学习模型时这些月度特征比原始逐日数据更有预测能力和解释性在新疆这种降水稀少的区域尤为明显。3. 图表选型与 ECharts 可视化大屏新疆降水空间分布与趋势预测的核心呈现3.1 可视化技术选型ECharts 在气象降水场景中的适用边界在数据可视化选型上气象领域常见的是 Panoply、GrADS、NCL 等专业工具但作为大数据分析项目展示Web 端交互式大屏的表现力和传播性远胜传统静态图。ECharts 作为国内生态最成熟的图表库在数据可视化大屏场景下有三点明显优势内置地图组件支持 GeoJSON 自定义轮廓热力图与等值线图对网格化数据渲染性能不错以及 tooltip 联动在时序巡检中体验很顺。企业级数据可视化大屏往往要求同时呈现概览、趋势和分布三个维度ECharts 的多图联动正好对应这种布局。新疆降水可视化核心在于空间插值——站点数据是散布的但人眼理解需要连续色块。我会用 Kriging 插值把站点雨量映射到 0.1°×0.1° 网格约 1000 行代码的数据矩阵再用 ECharts 的visualMap分段展示。这里有一个关键参数visualMap的splitNumber不宜过大降水色阶建议分为 6 段左右因为新疆大部分区域月降水量集中在 0 到 30mm分段过细反而看不出地域差异。3.2 地理热力地图的实现天山北坡与南疆盆地的空间呈现以下是基于插值结果绘制新疆降水热力地图核心代码片段var precipitationData []; // 从后端接口获取的插值网格数据 var geoJson await fetch(./xinjiang.json).then(res res.json()); echarts.registerMap(xinjiang, geoJson); var chart echarts.init(document.getElementById(precip-map)); var option { tooltip: { trigger: item, formatter: function(params) { return params.name br/月降水量 params.value.toFixed(1) mm; } }, visualMap: { min: 0, max: 30, splitNumber: 6, inRange: { color: [#d9f0d9, #b8e2b8, #8fca8f, #5aa75a, #2f7f2f] }, text: [多雨, 少雨] }, geo: { map: xinjiang, roam: true }, series: [{ type: map, map: xinjiang, geoIndex: 0, data: precipitationData }] }; chart.setOption(option);这段代码里有几个实际运营场景中容易被忽略的细节GeoJSON 需要从标准新疆地图矢量数据转换而来坐标需要 WGS84 坐标和站点经纬度对齐才不会有偏移visualMap的inRange颜色建议从浅到深表达降水量递增顺序颠倒会影响阅读直觉roam: true允许大屏端用户拖拽放大地图避免局部区域站点过密时信息重叠。如果后端返回的插值数据量大建议用 Web Worker 预处理避免主线程阻塞导致地图拖动卡顿。3.3 时序趋势图与降水集中度分析的有效搭配大屏上除了地理热力分布时序展示同样重要。新疆降水的一个显著特征是集中在夏季以及降水呈逐年微弱波动直接画全序列折线图信息量很少。我通常用双轴图柱状展示逐年总量折线展示降水集中度指数PCI计算公式为各月降水的平方除以年总量平方和PCI 大于 80 表示降水高度集中。这样一张图既能看出整体年际趋势又能看出季节分配的集中特征对后续机器学习建模时的季节性解释也有直接支撑。// 垂直布局时速览图 var trendChart echarts.init(document.getElementById(trend-chart)); trendChart.setOption({ xAxis: { type: category, data: yearList }, yAxis: [ { type: value, name: 年降水总量 (mm) }, { type: value, name: PCI指数, min: 50, max: 100 } ], series: [{ name: 年总量, type: bar, barWidth: 12, itemStyle: { color: #2d8cf0 } }, { name: PCI, type: line, yAxisIndex: 1, lineStyle: { width: 2 } }] });这里PCI定义有很多种我在项目里习惯用 Oliver 1980 年提出的修正公式它对零降水月份的处理在实际观测数据中表现稳定。若直接输出 PCI 原始值需要保留两位小数并在 tooltip 里加说明不然大屏观众很难快速理解 75 和 85 之间的差异。4. 机器学习在降水预测中的应用特征重要性排序与几种模型对比4.1 输入特征与目标变量的定义月尺度预测是最可行方案降水量预测在气象学中属于时序预报范围要做逐日精确预测需要气象物理模型或大尺度环流因子这在毕设场景里不现实。常见做法是把目标定义成次月降水量特征使用过去 12 个月的月度降水序列、季节均值、厄尔尼诺指数、站点海拔与经纬度。选择月尺度有三个实质理由维数不过高数据质量更可靠在新疆降水高度季节化背景下月份是天然强特征后期可视化展示时月尺度折线和大屏时间轴搭起来更顺手。在特征工程上我强烈建议加入降水的滞后特征和滚动均值特征这样能捕捉降水自身的时间依赖性。新疆降水变化跟全球气候驱动因子有一定关联但直接拿原始海温数据做特征并不合适需要降维后使用例如 EOF 分析提取前三个主模态。# 构造机器学习数据集 features [] for st in station_groups: df_st station_groups[st] df_st df_st.sort_values(date) # 过去12个月的连续无降水日数特征 for lag in range(1, 13): df_st[fprecip_lag_{lag}] df_st[precip].shift(lag) # 滚动均值最近3、6、12个月 df_st[rolling_mean_3] df_st[precip].rolling(3).mean() df_st[rolling_mean_6] df_st[precip].rolling(6).mean() df_st[rolling_mean_12] df_st[precip].rolling(12).mean() features.append(df_st) dataset pd.concat(features) dataset dataset.dropna() X dataset[[precip_lag_1, precip_lag_2, precip_lag_3, rolling_mean_6, rolling_mean_12, lat, lon, elev, month]] y dataset[precip].shift(-1) # 目标下月降水量这个特征集并不追求大而全而是抓住气象序列的周期性和空间背景。precip_lag_1和precip_lag_2通常贡献了半数以上的模型解释力。month特征以数值形式使用意味着 12 月与 1 月在数值上相距很远这不符合实际因此需要做三角函数编码把“月份相邻”这一事实嵌入模型输入。同样lat和lon保留也可以但需要确认它们与海拔没有共线性否则模型的特征重要性会被空间变量挤占。4.2 模型选型随机森林、XGBoost 与 LightGBM 在稀疏数据上的表现回归任务上经典线性模型对这样的零膨胀分布很难拟合LSTM 又需要更长序列才能发挥优势月尺度样本量通常只有 200 到 400 条纯粹使用深度学习容易过拟合。常见做法是使用集成学习树模型随机森林、XGBoost 与 LightGBM 可以都在同一份数据集上做交叉验证然后按 R² 和 MAE 选择最优。from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_absolute_error, r2_score X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, shuffleFalse # 时间序列不能随机打乱 ) model RandomForestRegressor( n_estimators500, max_depth8, min_samples_leaf3, random_state42 ) model.fit(X_train, y_train) y_pred model.predict(X_test) print(MAE:, mean_absolute_error(y_test, y_pred)) print(R2:, r2_score(y_test, y_pred))代码里最需要用心的是shuffleFalse。时间序列数据一旦随机切分训练集和测试集之间会混入未来信息指标虚高。随机森林在这个任务里通常能达到 MAE 3 到 5mm 的水平R² 在 0.5 到 0.7 左右。对比来看LightGBM 若加上linear_treeTrue在稀疏降水数据上往往会有更好的拟合度和更快的训练速度。模型的可解释性是重点报告里必须输出特征重要性排序。特征重要性结果表明precip_lag_1、month和rolling_mean_3通常排在前三位这其实呼应了一个朴素机制新疆月降水最强的预测因子就是“上个月下了多少”与“现在是几月”。把这两个特征加到模型后几乎没有其他变量能提供同等量级的增量信息。4.3 类别不平衡陷阱降水量为 0 的月份如何处理新疆许多内陆站的月降水为 0 或小于 0.1mm在真实数据集里出现频率很高。直接训练回归模型会让预测结果偏向于“少雨”方向这种均方误差驱动的收缩是大数据挖掘中极为常见的败坏模式。处理方式有两种一是构建两阶段模型先做分类判断是否为有效降水月再在有效月份上做回归二是在回归损失中提高非零样本的权重。第二种更好落地而且可直接在 sklearn 里通过sample_weight实现。# 两阶段方案中的第一阶段有效降水月分类 from xgboost import XGBClassifier train_mask dataset[precip_target] 0.5 # 定义为有效月 clf XGBClassifier(n_estimators200, max_depth6, learning_rate0.1) clf.fit(X[train_mask], (y[train_mask] 0.5).astype(int))阈值 0.5mm 的选取不是随意的它对应新疆气象业务中“有量降水”的起始值。二分类器在这个任务上最好能达到 F1 值 0.85 以上否则回归模型的误差主要来自于分类错误造成的误预测而不是回归本身的精度。把两阶段模型的结果同时放入可视化大屏还能提供“下月是否降水”和“降水量级”两层信息展示效果和解释性都更完整。5. 模型部署与可视化大屏落地预测结果服务化和空间插值展示的关键跳转5.1 用 Flask 将训练好的模型封装成预测接口模型训练完成后要想真正驱动大屏展示还需要在服务端部署推理接口。常见做法是用 Flask 写一个轻量 API加载训练好的joblib模型文件根据前端传入的站点经纬度和历史降水序列返回下一个月的预测值。这个方案适合毕设和轻量级应用不需要引入复杂的模型服务平台。import joblib from flask import Flask, request, jsonify import pandas as pd app Flask(__name__) model joblib.load(precip_model.joblib) app.route(/predict, methods[POST]) def predict(): data request.get_json() # data包含: station_id, lat, lon, elev, month, hist_precip_list feat build_features_from_history(data) pred model.predict([feat])[0] return jsonify({predicted_precip_mm: round(float(pred), 2)}) def build_features_from_history(data): hist data[hist_precip_list][-12:] feat { precip_lag_1: hist[-1] if len(hist) 1 else 0, precip_lag_2: hist[-2] if len(hist) 2 else 0, rolling_mean_6: sum(hist[-6:]) / min(6, len(hist)), rolling_mean_12: sum(hist) / min(12, len(hist)), lat: data[lat], lon: data[lon], elev: data[elev], month: data[month] } return [feat[precip_lag_1], feat[precip_lag_2], feat[rolling_mean_6], feat[rolling_mean_12], feat[lat], feat[lon], feat[elev], feat[month]]接口设计上要注意特征顺序必须与训练时完全一致这是最容易出 Bug 的地方。建议在build_features_from_history函数里输出特征列名并保存训练时的特征列表到 JSON 文件供服务端读取避免硬编码顺序。由于预测任务每月跑一次即可接口不需要高并发支撑Flask 默认单进程模型足够稳定。对于可视化大屏这个接口还可以暴露为/batch_predict一次传入所有站点批量返回预测结果前端再根据经纬度做插值渲染。5.2 利用服务端渲染或静态数据文件优化大屏加载性能当站点数量在 200 左右时批量预测的内存占用几乎可以忽略。为追求大屏首屏渲染速度可以把过去 30 年的站点降水和预测数据事先聚合成一个monthly_data.json文件前端直接 fetch 而不是每次从后端算。只有在大屏端主动点击“刷新最新预测”时才调用 Flask 接口这样能显著减少等待时间避免大屏冷启动时白屏时间过长。# 生成前端静态数据文件 python export_map_data.py --year 2024 --output ./public/data/xinjiang_precip_2024.json导出的 JSON 结构建议采用{ stations: [...], grid: [...], prediction: [...] }三段式。其中grid是 Kriging 插值后生成的空间网格prediction是模型返回的各站预测结果。地图热力层优先读取grid而 tooltip 详细数据则从stations取这样交互时不会因大范围重渲染而卡顿。如果网格数量超过 1 万个点还可在前端开启动画过渡或采样显示比如地图在低缩放级别只显示 5km 网格放大到站点级别后再展示更精细的等值面。ECharts 的setOption支持局部更新不要每次都替换完整 option 对象。用chart.setOption({ series: [{ data: newData }] })只更新 series 数据保留之前的 geo 和 visualMap 配置这样渲染开销大幅下降。大屏自动轮播时利用setInterval每 5 秒切换月份数据及时释放前一个图表实例能避免长时间运行后内存累积导致页面崩溃。对于在现代浏览器上的运行期稳定性可以用echarts.dispose()在切换页面时明确销毁实例。5.3 特征鲁棒性与业务鲁棒性遇到模型表现不稳定怎么办模型上线训练和离线训练之间经常出现差异主要原因是线上特征缺失或埋点不同。在气象场景下API 收到的hist_precip_list如果来自不同数据源可能会有批量缺失。补救方式是在build_features_from_history中统一回退策略最近月份缺失时用历史同月多年均值替代连续缺失超过 3 个月直接放弃该站预测并在数据集中标记缺测。把错误响应{error: insufficient history}明确暴露给前端大屏端对该站点显示灰色而不是用一个虚假数字继续渲染。这个处理比任何模型参数调整都重要——大屏上宁可缺测也不能污染数据可信度。在模型评估时除了 R² 与 MAE建议增加一个业务消耗指标在年降水量低于 150mm 的站点上单独计算误差。新疆南部站点如果模型的平均绝对误差达到 4mm对标其半年总降水 50mm这是一个不能接受的相对误差。建模时可以对这部分站点将sample_weight调高一倍让模型在干区的表现优先得到优化。这样做对于真正需要用大屏做水资源调度研究的用户远比追求全局 R² 更有价值。在干燥区降水序列里大量 0 值再叠加预测输出被压缩至接近 0视觉上看上去一目了然但这正是“零膨胀模型”的正常输出。应对办法是把目标变量从绝对降水量换成降水量百分位或对数值在展示端再反变换回来。对数值变换在反变换时要做偏差修正否则值域意义上的雨量会被系统性低估。实操上我用np.log1p作为目标变换输出后应用np.expm1还原并对比反变换值和原始值发现偏差在可接受范围内才可以交付大屏使用。这个流程虽然多花几步却是数据挖掘项目从“看起来像研究”推进到“真正能说服现场专家”的分水岭。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价