全国省市县三级逐日最低气温数据处理与GIS应用指南
发布时间:2026/10/11 17:01:20 锦皓数字建站

拿到这类数据包我最怕的不是文件太大而是打开之后“看起来正常、用起来全错”。1980-2024年全国省市县三级逐日最低气温数据听上去就是一张干干净净的Excel表加几个Shapefile但真放进GIS里操作编码、单位、日期格式、行政区划变动每个环节都能让你的成果图变成一张噪声图。下面这篇就把我从“解压数据”到“出图分析”整个流程里遇到的关键问题逐个拆开讲清楚包含字段结构、格式陷阱、应用场景、数据清洗和验证方法适合刚接触这类日尺度气象栅格/行政区统计数据的GIS从业者、气象分析人员和农业、能源领域的研究者参考。1. 数据集整体结构45年逐日记录到底意味着什么1.1 时间维度1980-2024的日历天数和序列组织方式1980年1月1日到2024年12月31日含首尾一共45个年份。很多人会想当然地认为45年就是45乘365天但里面还有12个闰年所以完整日历天数是16437天。这意味着如果你把一个县级、逐日、全字段的数据放在一张Excel表里全国大约2800个县级行政区累积下来接近5000万行记录。所以这类分享数据基本不会真的给你一个“无敌大工作簿”更常见的组织方式是“按年份拆分”“按月份拆分”或者“按日期拆出成千上万个文件夹”。拿到手之后不要急着双击打开最大那个Excel先看目录树。目录里通常会有年份文件夹里面再按月份或日期放置文件。对日尺度数据来说日期是可检索性最高的维度也是后续做时间序列分析时最容易踩坑的地方。如果数据包结构很混乱我的建议是先统一整理为“日期、行政区划代码、行政区划名称、最低气温”四列的长表再存成Parquet或CSV后续随便怎么筛选聚合都顺畅。1.2 空间维度省、市、县三级的组织逻辑“省市县三级”不是普通的粒度堆叠它意味着同一个时点同一份气温被重复记录了三轮省级一份每天大约几十行市一级一份每天大约三百多行县一级一份每天大约两千八百多行。三级数据单独看都能用组合起来更有意思。基层研究用县级区域对比用市或省不同层级之间可以互相验证。比如县级数据某天出现一个异常低温值用上一级市级面的均值去核验往往能很快判断是真实极端事件还是数据错位。需要留意的是行政区划不是一成不变的。过去几十年里撤地设市、撤县设区、设立新县级单位这些事情非常多。因此数据包里的“现行行政区划”和“历史某一年的真实区划”可能存在差异。做跨年对比时尽量使用“行政区划代码”而不是行政区划名称来进行关联和匹配名称相似但代码不同的情况在长期序列里几乎必然存在。1.3 Shp和Excel的定位一个管图一个管数Shp和Excel不是同一份数据的两种简单复制它们服务的分析流程完全不同。Shapefile适合空间可视化。一个县一个面要素属性表里挂着温度值打开GIS就能画出等值区域图。但Shapefile由多个同名文件组成.shp、.dbf、.shx、.prj等发送或拷贝时一旦漏掉.dbf属性表就全空了。温度数据的关键字段都在.dbf里所以看到.shp文件时务必确认旁边几个辅助文件都在。Excel则更适合做统计建模。数据按行列存放日期是一列、区域代码是一列、温度是一列用Pandas或R语言读进来后可以轻松做分组统计、面板回归、机器学习特征工程。Excel格式最大的问题在于数据量太大时运行卡顿所以建议不要直接打开编辑先转化成更为高效的数据格式。维度Shapefile格式Excel格式核心用途制图、空间分析、切片展示表格清洗、统计建模、跨表合并最小分析单元一个行政面要素一行时间-区域记录易碎点多个辅助文件缺失、编码乱码行数过多、日期类型混乱适用人群GIS制图师、遥感分析者数据分析师、科研人员2. 打开文件前必须弄懂的字段与格式细节2.1 Shapefile属性表里的中文字段和编码问题中文属性表乱码是我见过最多的“假故障”。表现很直接QGIS里打开属性表省、市、县名称全部变成“锟斤拷”或者“”一类内容。原因不是数据坏了而是Shapefile的.dbf文件本身用GBK或GB2312编码存储中文字符而GIS软件默认按UTF-8解析。解决办法很简单在加载Shapefile时把数据源编码手动指定为GBK或GB18030。QGIS的“数据源编码”选择里通常有“GBK”“System”等选项切换后重新加载即可。如果所有办法都试过仍然乱码可以用Notepad打开.dbf附近的.cpg文件查看编码声明再按声明指定编码。编码问题解决之前最好不要对字段做任何重命名或导出操作避免把错误编码固化到新文件里。2.2 坐标系统、单位和读数精度的判断这类行政区温度数据大多是经纬度坐标系常见的是WGS84或CGCS2000投影坐标也可能出现。打开图层后如果和在线底图错位很远先看是否把十进制度数当成了平面坐标如果只是几十米的偏移可以检查是不是参考椭球或坐标系定义略有差异。对气温数值来说坐标系影响不大但平面投影与经纬度存储会影响距离计算和面积统计。我的习惯是日常查看用经纬度坐标计算县域面积或做格点插值时再投影到当地合适的平面坐标系。2.3 温度单位直接是摄氏度还是缩放了10倍这是最隐蔽的坑之一。很多气象数据为了节省存储空间会把温度乘以10记录成整数比如-3.5℃写成-350.6℃写成6。如果你没有看字段说明直接把-35当零下35度画图整张图就会“异常偏冷”而且很难发现。判断方法很简单载入数据后先看最低气温列的取值范围。如果大部分值落在-450到400之间基本可以确定是0.1℃单位如果正常分布在-50到45之间才是标准摄氏度。对于0.1℃单位的数据处理时除以10即可。提示不要在看到“-320”时先怀疑极端寒潮先检查缩放系数。这类错误在全量数据里不会只出现一两个而是整体偏移特征非常明显。2.4 Excel日期列的三种存储形态与解析方法Excel日期列常见三种形态处理方式完全不同存储形态示例处理方法真日期格式2024-01-15直接转成datetime对象字符串格式20240115用format%Y%m%d解析数字序列45277从1899-12-30起累加天数数字序列在Pandas里不自动识别读出来是一列整数。解析方法为import pandas as pd df[日期] pd.to_datetime(1899-12-30) pd.to_timedelta(df[日期数值], unitD)为什么是从1899年12月30日而不是1900年1月1日这源于历史软件日期序列的起点规则。1980年以后的数据不会碰到1900年闰年bug的影响所以直接用这个基点转换是安全的。3. 这套数据在真实业务中值钱的应用方向3.1 农业霜冻界定、无霜期和冷害监测农业生产里最低气温比平均气温更能定义霜冻风险。比如某些果树在花期遇到-2℃以下的低温就可能造成减产春季最后一次霜冻日推迟播种和定植计划就要跟着调整。用逐日最低气温数据可以计算县域无霜期长度df[霜冻日] (df[最低气温] 0).astype(int) # 每年最后一次霜冻日 last_frost df[df[霜冻日] 1].groupby([年份, 行政区划代码])[日期].max() # 每年最早一次霜冻日 first_frost df[df[霜冻日] 1].groupby([年份, 行政区划代码])[日期].min()这样的指数比单看某一天的低温值更有业务指导性。搭配产量历史数据就能评估某个县域霜冻灾害年景。3.2 能源供暖度日数的简化估算能源调度通常关注供暖度日数HDD标准定义依赖日平均气温。如果数据包没有平均气温只有最低气温可以拿最低气温做简化近似比如设定一个低温阈值把低于阈值的部分累加作为冷量强度指标。我不建议照搬标准公式因为用最低温代替平均温会系统性低估实际供暖需求。更合理的做法是把最低气温和当地负荷历史数据做回归自己标定参数。逐日数据的好处就是样本量大一年365个点足够你做一个像样的相关性分析不必依赖别人给你的固定系数。3.3 公共健康与交通寒潮持续事件识别健康风险研究里极端低温的持续天数比单日最低温更重要。连续三天以上、日最低气温大幅低于当地多年同期均值往往对应着心血管疾病风险上升和道路结冰事故增加。用这套数据可以统计每个县级区域每年“低温事件”发生的次数、平均持续时间和最早开始日期。加上行政区划经纬度还能判断风险的空间集聚特征为应急预案制定提供基础图层。4. 数据清洗过程中最容易踩的四个坑4.1 乱码不是文件损坏而是DBF编码识别失败排查链路应该是现象是属性表中文乱码第一步检查是否所有字符列都乱码还是只有部分列第二步打开GIS数据源编码选项尝试GBK、GB18030、UTF-8三种第三步如果仍有问题检查.cpg文件或直接用文本工具查看.dbf开头的字符集标记。乱码解决后建议把数据导出为GeoPackage格式后续不再受编码困扰。4.2 数字“0”到底是真零度还是缺测标记很多气象数据用特殊值标记缺测常见的有9999、-9999、999999。但更低级的陷阱是“0”既可能是真实的0.0℃也可能是无效值。我的经验是结合日期和空间位置一起判断盛夏时节内陆多个县集体出现最低温0℃基本是异常冬天某高海拔县出现0℃可能完全正常。清洗时可以先把超出合理物理范围的值统一转为NaN再统计缺失率。比如摄氏度单位下可以把小于-60℃和大于50℃的过滤掉。df[最低气温] pd.to_numeric(df[最低气温], errorscoerce) df.loc[~df[最低气温].between(-60, 50), 最低气温] None4.3 按名称合并时行数暴涨或者大量缺失用县名做关联是非常顺手但非常危险的操作。同一个县名在不同年份可能对应不同代码不同县也可能有类似名称。合并之后行数异常增多多半是连接字段存在重复大量缺失则可能是代码或名称存在前导零丢失。规范的字段类型必须一致并统一为六位字符串df[行政区划代码] df[行政区划代码].astype(str).str.zfill(6)不要存成数字否则前导零消失后代码就错位了。4.4 行政区划变动导致的历史序列不连续这里不细说具体某个地方的变化但从全国尺度看过去几十年的行政区划调整频率相当高。你手上这份数据的“行政区划代码”对应的可能是2020年或2024年的行政区划版本而你要研究的年份可能还在旧版本里。建议做法分三步第一对研究期内的行政区划代码做去重和变化检测第二如果代码变化频繁尝试用“年份区域映射表”做历史版本归并第三如果你只需要制图分析不必强行把历史数据统一到最新边界可以用“当时的行政区划”出历史图用“最新边界”出现状图两个图不要混用。5. 实操演示把特定日最低气温挂到县级Shapefile上5.1 第一步读取并清洗Excel数据假设你的文件名是“全国县级逐日最低气温_2024.xlsx”读取时注意指定代码列是字符串。import pandas as pd raw pd.read_excel( 全国县级逐日最低气温_2024.xlsx, dtype{行政区划代码: str} ) raw[日期] pd.to_datetime(raw[日期].astype(str), format%Y%m%d, errorscoerce) raw[最低气温] pd.to_numeric(raw[最低气温], errorscoerce) # 过滤不可信极值 raw raw[raw[最低气温].between(-60, 50)] # 筛选出你要出图的那一天 target raw[raw[日期] 2024-01-15].copy() target[行政区划代码] target[行政区划代码].str.zfill(6)如果字段名不同根据实际文件修改列名即可。读取后别急着合并先打印target.head()看一眼。5.2 第二步用行政区划代码关联空间图层用GeoPandas读取县级行政区Shapefile同样把代码列处理成六位字符串。import geopandas as gpd gdf gpd.read_file(县级行政区划.shp, encodingutf-8) gdf[行政区划代码] gdf[行政区划代码].astype(str).str.zfill(6) merged gdf.merge( target[[行政区划代码, 最低气温]], on行政区划代码, howleft ) print(merged[最低气温].isna().sum()) # 查看未匹配上的县这一步如果大量缺失首要检查不是几何问题而是代码是否都是字符串且位数一致。也可以顺便看看目标文件里是否有重复代码用target[行政区划代码].duplicated().sum()检查。5.3 第三步导出与渲染合并完成后直接导出为GeoPackage避免再把Shapefile那一堆小文件拷来拷去。merged merged.to_crs(EPSG:4326) merged.to_file(2024-01-15全国县级最低气温.gpkg, driverGPKG)后续在QGIS里打开这个GeoPackage按“最低气温”字段做分级设色即可。配色建议用蓝色系代表低温、红色系代表高温这样图面语义更直观。别忘在出图标题里写上具体日期因为逐日数据一旦混用日期很容易出“图上日期和文件名不一致”的低级错误。6. 拿到数据后建议先做的四项验证6.1 用一场你记得住的强降温过程来复核不论数据生产方说自己的数据多么准确我都建议先找一次自己经历过的、印象深刻的强降温过程做复核。选几个你熟悉区域看那几天最低气温的变化趋势是否符合记忆和常识。如果趋势对说明数据的时间连续性基本可靠如果完全对不上就要怀疑日期列是不是存在整体偏移或时区问题。6.2 绘制年度最低温序列识别整体异常把全国或研究区域每年最低温度取出来画一条折线正常情况下不会出现毫无原因的骤变。异常的骤升骤降往往对应数据处理错误比如某一年没有除以10、某一年缺失值没有被正确识别。检查代码year_min raw.groupby(raw[日期].dt.year)[最低气温].min() print(year_min)看到这种汇总图再回到细节里查找具体日期比直接全表搜索更高效。6.3 空间相邻检查边界两侧应当平滑过渡把某一天的县级最低气温渲染到地图上肉眼观察相邻县域之间有没有大跨度跳变。自然情况下平地区域相邻县域温差通常不会特别夸张如果一块区域被一条明显“撕裂”的边界分为左右两半大概率是行政区划代码错位或某个文件字段顺序不对。这种检查不能只看最高最低值要看空间格局是否“讲得通”。地形复杂的山区例外高差会带来明显温差这时要结合DEM判断。6.4 缺失率统计与插值决策逐日数据经历多年整理几乎不可能零缺失。对每个年份、每个月统计缺失率会直接影响后续建模时是否要做插值。raw[月份] raw[日期].dt.month missing raw[raw[最低气温].isna()].groupby([日期]).size() missing.to_csv(缺失日期统计.csv, encodingutf-8-sig)如果缺失只集中在少数几天通常可以直接剔除如果某个月成片缺失可能要考虑线性插值、空间插值或者使用上一级行政区域均值做填充。填不填充没有绝对标准但一定要在分析报告里写清楚不然别人复现时会得出完全不同结果。最后再分享一个小技巧这类上传分享的数据文件往往没有附带非常详尽的字段说明花半小时做一个压缩包内文件清点再按本文的思路做一遍字段和单位检查远比直接拖进软件跑分析划算。尤其在多人协作时把“单位是摄氏度还是0.1℃”“日期格式是什么”“行政区划版本是哪一年”这三条写清楚整个项目的返工率能降下一大截。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。