省-市-县三级气象气候数据集处理全流程:从原始观测到面板数据
发布时间:2026/9/9 17:46:13 锦皓数字建站

做气候项目最怕的不是模型跑不出来而是数据到了手里根本不能用。2011—2024年、覆盖省、地市、区县三级的日尺度气象气候数据听起来好像就是“整理一批表格”真正开始做的时候才发现站点缺测、单位不统一、行政区划调整、不同来源的降水口径不一致每一步都在磨你的耐心。我这两年为完成这套数据集把公开站点观测、格点再分析资料、统计公报全部梳理了一遍整理出一套能从原始记录直接走到省市县面板的完整流程。这篇就写给准备做同类数据研究或业务计算的你里面既有整体设计思路也有具体到能改代码直接用的处理套路还有我实际踩过的坑。不管你是做气候变化趋势分析、农业气象灾害评估还是做清洁能源选址、保险理赔量化这类数据都是绕不开的底座。很多朋友刚开始下载数据时兴致很高等看到几十个文件、上千万行记录就不知道怎么办。这篇文章我尽量讲透数据怎么定范围、清洗有哪些隐藏关卡、多级行政口径怎么对齐、聚合时到底该求和还是求平均、最后又怎么证明这套数据是可靠的。文章比较长建议收藏后按自己需求跳着看。1. 数据设计思路与整体定位1.1 为什么要做省-市-县三层数据量级怎么估一开始我其实只想要县级数据但做到后面发现单纯做县级会有很多麻烦。省、市、县三级口径放在一起本身就是一个天然的校验金字塔下面的区县数据聚合到地市再聚合到省每一层都能对上才说明数据是可靠的。省级适合看大尺度趋势地市级适合做区域间的对比分析而县区级则是很多政策评估和保险模型的最小空间单元。一套数据同时支撑三层省去了反复下载、反复清洗的重复劳动。做之前最好先对数据量心里有数。2011到2024年是14年其中2012、2016、2020、2024是闰年总天数大概是5114天。如果按2800多个县级行政区来算单要素每天的记录就是2800多条一年就是100多万条14年下来一个要素就有1400万行左右。我做的这套涉及气温、降水、湿度、风速、日照等多个要素如果再展开成长表规模直接到亿行级别。这个量级用Excel是肯定玩不转的一开始就要做好用脚本处理的准备。1.2 核心气象要素怎么选气象数据要素很多但绝大多数分析场景并不需要全部。我最后选定的核心要素是日平均气温、日最高气温、日最低气温、日降水量、日平均相对湿度、日平均风速、日照时数。这七个要素基本覆盖了“热量、水分、风能、辐射”这几个主要维度无论做积温、干燥度、风功率密度还是极端高温事件都能在这些基础上派生出来。如果只做基础气候统计这七个就够了。但如果你的项目涉及蒸发估算、地表能量平衡或者空气质量模拟那还得额外扩展水汽压、气压、地表温度、蒸发量等要素。我的建议是前期宁可多保留也不要后面再回头补。因为重新下载和清洗一套要素的成本比一开始多存几个字段要大得多。要素字段最好同时保留原始值和换算值比如风速既要保留原始m/s也要在需要的时候能方便地换到0.1m/s精度避免不同来源混用导致量级错误。1.3 数据源怎么搭站点观测和再分析资料各有各的用处市面上的气象数据来源大致分两类。一类是站点观测资料来自全国分布的国家级和区域级自动站优点是“实测、准确”缺点是站点分布不均匀尤其是县区尺度经常出现一个县一个站点都没有的情况。另一类是格点再分析资料比如欧洲中心ERA5这类产品通过数值模式把卫星、探空、地面观测融合成规则网格优点是空间连续、要素齐全缺点是它本质上是一种“模式产品”和真实观测之间总有或多或少的偏差。我的做法是“站点做骨架再分析做辅助”。具体来说凡是国家站点能覆盖到的县区以站点观测为准站点明显不足或完全空白的县区用再分析格点数据做插补和参考。两套数据在融合之前必须做交叉校验不能直接拼在一起。大部分数据都能通过公开渠道申请获取虽然流程繁琐但胜在规范再分析资料也有公共数据门户可以直接注册使用。行政边界我用的是公开的省市县三级基础地理数据处理时统一转换成同一套坐标系统避免边界和站点坐标对不上。1.4 最终成品的目标形态我给自己定的成品标准是一张长表每条记录包含行政区代码、名称、日期、要素名称、数值、是否插补标记、数据质量标记。长表的优点是后续透视、筛选、绘图都方便如果某些场景需要宽表比如每个要素一列也可以在读取后做一次pivot。从项目一开始就确定好目标形态整个处理流程才有明确方向不会做着做着突然发现输出结构没法用。2. 清洗与质控数据能不能用的分水岭2.1 原始数据常见的五个坑原始数据看着整齐实际打开后问题很多。我归纳了五个最常遇到的坑基本每次整理都会撞上。第一个是时间格式不统一。有的文件里日期是字符串有的是时间戳还有的是年、月、日拆成三个字段。这个问题不难解决但很耗时间最好在读取阶段就直接统一成标准日期格式。第二个是缺失码混乱不同的数据源用-9999、9999、32700来标缺失有的甚至直接用空白单元格这些都要提前做映射。第三个是重复记录自动站分钟数据转日值的时候同一天很容易出现多条记录可能是设备重复上传也可能是不同时段的分段记录需要按站点加日期做去重。第四个是单位制不统一降水量有的给毫米、有的给0.1毫米风速有的给m/s、有的给0.1m/s换算错一位数后面全错。第五个是站点经纬度坐标的小数位不一致有的给到秒有的给到小数点后四位度直接拼map的时候点会跑到海里去。注意处理前期绝对不要把原始文件删掉。我试过为了省空间清洗完就删后来发现漏了一个单位换算整批数据都要从原始格式里重新算悔到肠子青。原始数据是唯一的“事实来源”留到项目全部结束再清理。2.2 缺失值分级处理不搞一刀切缺失值是这种长序列数据集里最绕不开的问题。我试过最简单粗暴的“直接删除缺失行”结果在极端降水事件分析里漏掉了不少关键记录后来再也不敢这么用。比较稳妥的做法是先分清楚缺失类型是某个站点几天坏掉了、季节性停测还是整段数据没下载到。我最后采用的分级策略大概是缺失比例低于1%这种随机小缺测可以用前后日值线性插值或者用邻近站点的回归估算来补缺失比例在1%到20%需要借助周边站点的相关性来做填补加上再分析数据的参考值同时打上“插补”标记如果某个县或某个时段缺失超过20%就不再强行填补直接在该时段留下空值并写入质控记录。因为数据样本已经少到不足以支撑可靠的插补时硬填进去的“数值”只会给后续建模引入系统性误差。对于温度、湿度这类连续性要素邻站回归的效果一般不错对于降水这种离散性强的要素插补会低估极端值。这也是为什么成品表里一定要有“插补标记”字段下游分析时可以单独做敏感性测试。如果你的项目对数据精度要求特别高比如做气候极值研究我甚至建议连1%以内的缺测都直接用“空值标记”处理让模型自己决定怎么对待这些缺失。2.3 异常值先标记再人工核不机械修改异常值判定比缺失值更棘手因为气象数据里的“异常”往往是相对的。一次降水量超过300毫米在大陆性气候区几乎是天方夜谭但在沿海台风影响区就有可能出现。所以我用的异常检测分三层第一层是气候极值检查也就是所有数值必须落在物理合理的区间内比如气温不可能低于-80℃、降水不可能为负第二层是变量内部一致性检查比如一天的最高气温不能低于最低气温相对湿度超出0到100就要怀疑第三层是空间一致性检查拿目标站点和周围几个站点的同期值对比如果差值大到离谱就标记出来。遇到标记出来的异常值我的原则是“宁可保留一个可疑值也不轻易把它改成某个好看的数字”。处理方式是把异常值置为缺失再走缺失值填补流程同时在质控日志里明确记录“哪年哪月的哪个站点因为什么原因被剔除”。这样下游分析中如果结果出现异常还能回溯到源头而不是面对一个被改得面目全非的“干净”序列。2.4 行政区划代码一个容易被严重低估的麻烦做省、市、县三级数据行政区划代码是贯穿始终的主键。但2011到2024年这14年恰好处在区划调整比较频繁的时期。县改成区、县级市升地级市、两个县合并、开发区代管乡镇这些调整在代码表上都会引起连锁反应。同一个地理位置上可能2015年之前叫县2015年之后变成了市辖区代码和名称全变了。我一开始没太在意等到做地市级汇总时发现了严重问题某个地级市下辖的区县列表不同年份出现不同数量汇总数据直接断裂。解决办法是建立一张“行政区划动态对照表”每一行记录县级代码、名称、所属地市、所属省份以及该代码的有效起止年份。处理历史年份数据时用当时的代码来匹配但在跨年份分析时再统一映射到一套稳定的“当前口径”上。这个对照表是整个数据集的基础设施没有它任何聚合层面的分析都不可信。3. 实操过程从原始记录到省市县面板数据3.1 项目目录与命名规范数据项目最怕做成一团乱麻。我现在的习惯是开工前先把目录结构定好obs/raw/ 存放下载的原始数据按要素和时间分文件 obs/clean/ 清洗后的逐日站点数据 data/city_map/ 行政区划动态对照表、边界数据 data/final/ 最终输出的省市县面板 report/ 处理日志、质控报告、版本说明每个文件命名也统一遵循“要素_年份_层级.csv”的格式比如tmean_2011_county.csv。手工操作和脚本处理都要严格遵守这个命名规则后续写批量处理时才能用通配符一遍过。目录结构和命名规范看似简单实际上能帮你省掉大量“这个文件是什么时候生成的”的困惑。3.2 站点经纬度怎么落到区县把站点数据匹配到县区是最基础也是最重要的一步。核心逻辑是“点面包含判断”把站点经纬度作为点坐标把县区边界作为面对象用地理计算判断这个点落在哪个面里。我用的工具是Python的geopandas库处理起来非常直接。import pandas as pd import geopandas as gpd # 读取站点坐标和日值数据 site pd.read_csv(obs/raw/site_info.csv) obs pd.read_csv(obs/raw/tmean_2011.csv) # 转换成GeoDataFrame使用WGS84经纬度坐标 site_gdf gpd.GeoDataFrame( site, geometrygpd.points_from_xy(site[lon], site[lat]), crsEPSG:4326 ) # 读取公开的县区边界数据 county gpd.read_file(data/city_map/county_border.shp) # 点面空间连接得到每个站点所属县区代码 site_match gpd.sjoin(site_gdf, county, howleft, opwithin) # 合并回原始日值数据 df obs.merge(site_match[[site_id, county_id, city_id, province_id]], onsite_id, howleft)实际项目里站点坐标不一定总是和边界完全对齐特别是在县级边界附近。一个站点的坐标可能因为精度问题落在县城边界外几百米结果被分配到邻县去了。这种情况下需要人工复核判断这个站点的气候代表性到底归哪里更合适。另外我做匹配时还会保留两个字段主归属区县和邻近区县列表在县界附近或复杂地形条件下这个前置工作给后面分析很大的灵活度。3.3 无站点区县的数据怎么补全国县级单位几千个站点数量是远不够全覆盖的。大量县区境内根本没有国家级自动站有些即使有站也可能建站时间晚覆盖不到2011年。对这类区县我的做法是“邻站反向距离加权插值”也就是IDW。先筛选出目标县质心周围一定范围内的站点一般是方圆60公里内再按距离的倒数作为权重对站点值进行加权平均。这里有一个容易被忽略的细节地形对气象要素的影响很大。两个站点距离只有20公里但中间隔了一座山气温和降水就可能差很多。所以在山区我还会额外加一个海拔修正项用气温垂直递减率做粗略调整。插补后的数据一定会在“插补标记”字段里写清楚这样下游做趋势分析时可以单独考察“真实站点数据”和“含插补数据”两组结果的差异。如果一个县完全被插补覆盖比如十几年没有一个真实观测我会在质控报告里明确标注建议下游分析谨慎使用这个县的绝对数值。3.4 日值到月值、年值的聚合口径从日值聚合到月值、年值看似是简单的分组求均值或求和实际有非常多的隐藏选择。我最后确定的聚合规则如下要素日到月月到年备注平均气温日均值求算术平均日均值求算术平均也可基于日平均序列计算月均温最高/最低气温逐日值取月内平均逐日值取年内平均极端值场景需另行提取极值降水量逐日降水量求和逐日降水量求和不可用月均乘天数反推相对湿度日均值求算术平均日均值求算术平均线性平均存在轻微误差风速视目的而定通常用日均值平均视目的而定风能评估建议用风速三次方平均日照时数逐日值求和逐日值求和按小时数据转换时注意分钟单位换算最容易出错的是年降水量。如果先算月平均再乘12看起来是“平均”的概念实际上完全不对年降水量必须是每日降水量的累加。再比如每年的总天数不完全一样有些统计口径会把2月29日单拎出来处理不好年度均值就会偏差一点点。我的经验是所有分析永远从日值原始序列出发不要在月值基础上反复聚合否则误差会一层层累积。3.5 成品数据的存储与字段规范最终的数据集我保留了两套格式一套是CSV长表方便其他人直接用Excel或R、Python读取另一套是Parquet格式压缩率高、读取速度快给自己做分析的时候用。Parquet在亿行级别数据上比CSV有巨大优势同样是2011到2024年的全部要素CSV可能接近10GBParquet压完剩不到三分之一而且读取时还能只选需要的列。字段设计上我的成品表大致包含这些字段年份、月份、日期、省份代码、省份名称、地市代码、地市名称、县区代码、县区名称、要素代码、数值、单位、插补标记、质量标记、数据来源。这里的关键是把行政区划代码和名称同时保留因为代码会变动而名称在业务沟通时更方便。要素代码采用统一字典比如tmean、tmax、tmin、pre、rh、wind、ssd避免中文名在不同文件里叫法不一。3.6 全程留痕版本管理不是写给别人看的做这种长时间跨度的数据整理最忌讳的是“当时处理完就忘了”。我会在每个批次处理结束后写一个简短的处理日志记录这个批次用了哪些原始文件、做了哪些替换、插补参数是什么、质控前后记录数变化了多少。这些日志不需要很正式但必须能让你在三个月后还看得懂。我的习惯是每次跑完脚本第一时间生成一个report/YYYY_MM_DD_process_log.md哪怕只有三五行也比之后靠回忆靠谱得多。4. 常见问题与排查技巧实录4.1 一开始就要做“覆盖率报告”不要上来就清洗我犯过最大的错误之一就是拿到数据立刻做清洗和填补做到一半才发现某个关键省份的某年数据根本就没下载完整。最后那一整块全部作废重来浪费了大量时间。后来我给自己定了一条铁律不管拿到什么数据第一件事就是做覆盖率统计也就是每个站点、每个县区、每年到底有多少天的有效记录把覆盖率做成图表看清楚。这个过程看似多花一两天但能让你在开始清洗之前快速发现哪些年份、哪个地区的数据是“先天不足”的决定哪些时段可以用、哪些时段需要补、哪些时段只能放弃。4.2 区划变动导致县城序列断掉怎么处理才合理前面提到过区划调整的麻烦实际运行中还会遇到一种更隐蔽的情况某个县在2018年撤县设区它的县级代码直接从县序列里消失进入了地级市的市辖区列表。如果我在生成面板时用的是“最新区划代码”那2018年以前的县记录和2018年以后的区记录就会变成两条完全不同的序列。处理好这个问题的关键是维护好“历史代码—当前代码”的对应关系同时给每一个基本空间单元一个固定的连续性编号。简单说就是让分析代码认识“虽然名字和代码变了但这其实是同一个地方”。所有后续的分析只要是时间序列方向的都建议基于这个连续性编号来走。4.3 站点迁移会带来“假变化”这是均一性问题站点迁移是另一个能坑死人的问题。一个气象站如果在2015年从老城区迁到了郊区海拔变了、周边建筑环境变了温度序列会突然出现一个阶跃这在统计上很容易被误判成气候突变。我在县城尺度的数据里遇到过好几次温度序列前面明显偏低、后面突然普遍偏高拿去算趋势就会得到一个“异常偏暖”的结论。解决思路是找站点元数据里的迁站记录对迁移前后的分段序列做均值对比检验如果确认存在系统性偏移就对前一段做订正。这类订正不能做得太粗要保留原始记录并对订正过程做完整说明。4.4 降水日界一个特别隐蔽但影响巨大的口径差异气象观测对“某一天的降水量”往往不是按自然日0点到24点来算的。很多自动站系统采用20-20时口径也就是从昨天20点到今天20点之间的降水累积量算作“今天”的降水。当你同时使用不同来源的降水数据时如果没有把日界统一雨季的日降水序列会出现明显的错位个别日子的差异可以达到几十毫米。好在这个问题不太影响月总量和年总量因为累加起来的总额基本一样。但如果你做的是日尺度的事件识别比如日极端降水阈值超限口径不统一会直接导致漏判或误判。所以我在做多源数据融合前一定会先确认每个文件的降水日界再统一转换到自然日口径后再继续处理。4.5 数据量大、处理慢几个可落地的加速办法面对亿级行数据计算性能也是必须考虑的问题。我的几个实际经验是读取CSV时指定dtype把整数和浮点数都明确下来避免pandas去猜测类型内存占用可以直接降一截日期字段统一转成datetime类型后设为索引按年份分组聚合时能省下很多扫描时间中间结果一定要及时落盘保存而不是长期留在内存里跑否则一旦中途报错就要从头再来。还有一个更简单的操作按年份把数据处理拆成多个小批次处理完一年就保存一个中间文件最后再统一合并。这样做还有一个好处就是单个文件出错时不需要重跑全部数据。5. 数据质量怎么检验后续能用来做什么5.1 与公开发布的统计资料做对照验证数据做完最紧张的环节就是“到底准不准”。我会把县区数据聚合到省级与统计部门和气象部门发布的年度气候公报进行对比。主要看两个指标年平均气温、年降水量。我自己的容差标准是气温差在0.5℃以内、降水量差在10%以内就算合格如果超出这个范围基本可以断定数据在某个环节出了问题需要逐级往下排查是站点匹配错误、插补过度还是聚合口径不对。这个验证方法虽然粗但非常有效能快速暴露大范围内的系统性问题。5.2 空间一致性检查把异常的“斑块”在地图上找出来另一种非常有效的质控方法是空间可视化。把某一年的降水总量按县区填色画在地图上正常情况下相邻县区的数值应该是连续过渡的。如果某一个县的颜色比周围明显深很多或浅很多形成一个突兀的“斑块”那大概率是数据问题而不是真实气候现象。我在检查中就发现过某县因为某年有站点记录重复计入了两次导致年降水量翻倍后来在地图上看到一个亮斑才定位到这个问题。类似检查对气温、风速、日照时数都适用。5.3 这套数据真正能支撑的应用方向数据验证通过之后它能做的事情非常多。在气候变化领域可以做各省、市、县的气温趋势检验、降水变化归因、极端高温和暴雨事件频率识别。在农业领域可以做积温带划分、作物生长季长度分析、干旱灾害风险评估。在能源领域可以用来做风电和光伏资源的区域评估风能功率密度和太阳辐射资源分布都可以从基础数据中派生。在保险精算领域县级尺度气象数据是农业保险定价和极端天气指数设计的基础很多气象指数产品都依赖这类长序列。甚至公共卫生领域的热浪预警、传染病气象风险分析也离不开一套可靠的县级气象底数。提示无论你最终要做什么分析请一定在结果文档里写清楚数据版本号和处理日志。我见过太多人拿着别人处理好的数据直接跑模型最后没人知道那套数据里哪些值是插补的、哪些是实测的一旦结论被质疑根本无法回答。数据文档和数据本身同样重要。数据整理这条路上没有捷径但确实有好走一些的路径。我最大的体会是第一步就把质控做好、把口径想清楚后面建模阶段基本不用因为数据问题反复返工。能下载到的原始资料只是半成品真正可靠的数据集是一遍一遍洗出来的每一层清洗都要留证据、留版本、留标记。如果让我重来一遍我会从第一天就写好处理日志把中间结果全部存档而不是到项目快结束了才补文档。最后再分享一个小技巧当区县边界调整比较频繁时与其逐年用新旧代码去拼不如拿最新的边界把历史年份全部重新归属一遍虽然前期工作量会大一点但整条序列的口径一致性会好很多后面分析时你会感谢这个决定。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。