1. 数据集全景解读与应用场景定位
1.1 这套数据到底解决什么问题
去年年底,我接了一个农业干旱评估的咨询活儿,需要分析某省份过去几十年的湿度变化趋势,当时最大的痛点就是:相对湿度数据哪儿找?
气象站点的逐日观测数据倒是能拿到,但站点稀疏、分布不均,而且很多站点只有月值。要拿来做县级尺度的分析,要么自己做空间插值,要么去买商业气象数据,成本不低。后来我在整理数据资源时发现了这套1980-2024年我国省市县三级逐日相对湿度数据集,一下子解决了我的大问题。它把整个时间跨度44年、覆盖全国省市县三级的逐日相对湿度做成了可以直接用的面板数据,同时提供Shp和Excel两种格式,一端连着GIS空间分析,一端连着统计建模。
这套数据本质上是一份“网格化后落到行政区划”的再分析数据产品。背后是利用高分辨率气象再分析资料,经过降尺度、空间统计和行政区划面积加权平均处理后,把每个县级行政单元每天的相对湿度计算出来,再逐级汇总到市级和省级。所以它不只是某个站点的观测值,而是代表整个县域范围平均湿度的综合指标。我拿到数据后先用几个县的站点观测值做了对比验证,相关系数都在0.85以上,说明这套数据用于区域尺度趋势分析完全靠谱。
1.2 两种存储格式的定位与选择逻辑
Shp格式和Excel格式,本质上是为两种不同的工作流服务的。
Excel格式是二维表格结构,每条记录对应“县 - 日期 - 相对湿度”,这种长表结构非常适合用Pandas、R dplyr做数据清洗、透视、聚合和机器学习特征工程。我在做全省的湿度时空变化聚类时,就是用Excel格式直接读入内存,然后按县分组算均值、标准差、趋势斜率这些统计量,非常顺手。
Shp格式则是把相对湿度字段挂到行政区划矢量面上,每条记录对应“县 - 相对湿度”。它强调的是空间表达能力和地图制图能力。用ArcGIS或QGIS打开,能直接按色带渲染出某一天的全国湿度分布图,或者做逐年变化率的空间可视化。而且Shp天然带地理坐标系和投影信息,可以直接做缓冲区分析、邻域统计、与土地利用数据的叠加分析。
我的经验是:如果做定量统计和时间序列分析,优先用Excel格式;如果做空间制图、区域对比和地学分析,优先用Shp格式。两个格式之间转换也很容易,后面我会给出Python的处理模板。
1.3 典型应用场景与适配方向
从我实际经手的项目来看,这套数据至少能在四类场景里发挥作用。
第一类是农业气象灾害评估。相对湿度是病虫害发生发展的核心气象驱动因子之一,比如小麦赤霉病在抽穗扬花期遇上高湿天气就极易暴发。把逐日湿度序列和作物物候期叠加,可以算出“适宜发病日数”这样的指标,进而做灾害风险区划。
第二类是建筑与城市规划的防潮设计。建筑工程的防潮层设计高度、墙体结露风险评估,都依赖当地湿度的统计特征。44年的逐日数据,足够我们估算出极端高湿事件的重现期,这对基础设施设计标准的选择很有价值。
第三类是人体健康与环境流行病学研究。湿热天气与中暑、心血管疾病发病率的关联分析,需要把气象数据与病历数据做时空匹配。县域尺度的相对湿度数据正好可以在区县级健康统计中作为协变量使用。
第四类是生态与水资源研究。相对湿度影响蒸散发计算,是水文模型的常规输入变量。长序列的逐日湿度数据对校正和改进分布式水文模型很有帮助。
2. 数据结构深度拆解与字段逻辑
2.1 Excel长表字段设计解读
我拿到Excel后做的第一件事,就是看字段结构。这套数据的Excel版本核心字段大概是这样的:
| 字段名 | 类型 | 示例值 | 说明 |
|---|---|---|---|
| 省 | 文本 | 江苏 | 省级名称 |
| 省代码 | 文本 | 320000 | 6位省级行政区划代码 |
| 市 | 文本 | 南京 | 市级名称 |
| 市代码 | 文本 | 320100 | 6位市级行政区划代码 |
| 县 | 文本 | 江宁区 | 县级名称 |
| 县代码 | 文本 | 320115 | 6位县级行政区划代码 |
| 日期 | 日期 | 1990-06-15 | 标准日期格式 |
| 相对湿度 | 数值 | 78.5 | 单位:%,保留1位小数 |
这种长表结构叫“面板数据”或“Tidy Data”,每一行是一个完整的观测单元:某个县在某一天的平均相对湿度。它最大的好处是直接用Pandas的groupby就能做各种聚合,不需要先做透视表再清洗。
我特别提醒一点:行政区划代码务必按文本类型读取,不要用数值类型。不然县域代码前导零会被丢掉,比如代码是110105,一旦变成数字就变成了110105不会受影响,但如果是010开头的代码就麻烦了。好在当前我国县域代码没有前导零问题,但省级代码如果存成数值,在Excel里显示时会变成320000,导出成CSV后容易自动去掉后三位零,导致代码变成320,这就会直接影响后续与矢量面数据的匹配。
2.2 Shp矢量数据的属性表结构
Shp格式的文件打开后,属性表里大致会有这样几列:省、省代码、市、市代码、县、县代码,然后是一长串以日期命名的字段,比如humi_19800101、humi_19800102这样。这意味着一个县的所有逐日湿度值,都打包在一个面上,每列是一天。
这种“宽表”结构的优点是空间查询效率极高。想查某个时刻的全国湿度分布,选中对应的日期字段做符号化就行,完全不需要做连接操作。缺点也不难发现:如果想把某个县的湿度序列导出成时间序列格式,还需要做“面转属性”的转换工作。
Shp文件本身还包含投影信息,通常是GCS_WGS_1984地理坐标系。所以用QGIS或ArcGIS打开后能直接和最新下载的行政区划边界叠加,不用额外做投影转换。这一点对快速出图很重要,因为很多公开的省级或县级边界数据默认就是WGS84,能省不少对齐时间。
2.3 三级行政层级间的汇总逻辑
省市县三级之间是严格的父子关系:县级是基础数据单元,市级是下辖县域的面积加权平均,省级是下辖地市的面积加权平均。这个逻辑非常重要,因为你在Excel里看到的省级数据并不是简单地把省级代码对应的县代码数据再做个算术平均得到的,它其实是用面积权重处理的。
举个例子,假如一个市下面有两个县,A县湿度80%但面积1000平方公里,B县湿度60%但面积500平方公里,那么该市的平均相对湿度更接近80%的权重,约为73.3%。这一逻辑对大范围、湿度梯度明显的地区特别重要。如果你直接用简单算术平均去反推市级值,和数据集里给的市级数据会存在一定偏差,这不代表数据有错,而是汇总方法不同。
所以我在后续数据分析中,需要用到县市级数据做回归时,都会以基础县级数据为准,自己重新计算市级平均值,这样既保持了统计口径一致,也规避了面积权重与我的业务逻辑不符的问题。
3. 数据落地实操:清洗、加载与快速可视化
3.1 Excel数据的Pandas清洗与透视模板
我拿到数据的第一个习惯,是先做一遍完整的数据体检。用Python读取后,我会按这样一套流程处理。
import pandas as pd df = pd.read_excel("相对湿度_逐日_1980_2024.xlsx", dtype={"省代码": str, "市代码": str, "县代码": str}) df["日期"] = pd.to_datetime(df["日期"]) df["年"] = df["日期"].dt.year df["月"] = df["日期"].dt.month # 检查缺失 missing_ratio = df["相对湿度"].isna().mean() print(f"缺失比例: {missing_ratio:.4%}") # 检查异常值 outliers = df[(df["相对湿度"] < 0) | (df["相对湿度"] > 100)] print(f"异常值个数: {len(outliers)}") # 行政区划代码完整度 code_ok = df["县代码"].str.len() == 6 print(f"6位县级代码占比: {code_ok.mean():.4%}")这一套检查下来,如果缺失比例在0.5%以内、异常值可以忽略,就说明数据质量是靠谱的。我做过的某次校验里,这套数据的缺失值主要集中在个别县的早期年份,后续处理方案是用前后日期的线性插值补齐,或者直接筛掉参与某些需要逐日连续的模型运算。
实际统计分析中,最常用的是pivot之后把长表转成宽表:
pivot = df.pivot_table(index=["省代码", "市代码", "县代码"], columns="日期", values="相对湿度") trend = pivot.mean(axis=1)这样每个县就得到了44年的平均湿度,可以继续计算湿度变化趋势和极端高湿日数等衍生指标。
3.2 Shp文件在QGIS中的加载与专题制图
QGIS是开源软件,拿来处理Shp相当顺手。第一次加载Shp时,先把图层拖进画布,右键打开属性表,确认一下日期字段是否存在,然后进入Layer Properties - Symbology,把符号化方式选成Graduated,值选择某个具体日期的字段,比如humi_20100715,配色方案建议用“Blues”或“RdYlBu”。这样就能很直观地看出当天哪里潮湿、哪里干燥。
如果要做多年平均湿度的空间分布图,需要先在属性表里新增一个字段,用字段计算器算出所有日期字段的平均值。QGIS的字段计算器支持直接引用多个字段做表达式计算,但44年16000多个字段手工选工作量极大。我的做法是先用Pandas对宽表做平均,再通过join attribute by field把结果连回Shp属性表,这样能节省大量时间。
Shp出图时注意一点:如果发现地图上某些县域边界在过渡带呈现破碎状,大概率是原始边界数据包含飞地和争议区域。建议在出图前用QGIS的Fix Geometries工具做一次拓扑修复,能避免不少后患。
3.3 空间连接与属性回写的最佳实践
很多时候手头需要做的工作,是把湿度数据算到流域分区、气象站点或格网上。由于Shp文件的字段已经包含了行政区划代码,做空间连接最核心的一步就是“县级边界与目标区域做相交”。
用QGIS处理时,我一般先用“Join attributes by location”工具让目标区域与县级湿度面相交,把县级几何面积与湿度数据同时取出来,再按目标区域ID做面积加权平均。前面提过面积加权这个细节,在这里就是用来实现对流域或农业园区的平均湿度估计。
实际操作中,我发现Shp的几何面积需要先按投影转换成平面坐标再算,否则直接用WGS84经纬度计算的面积在高纬度地区误差会非常大。我的处理习惯是先把Shp投影到Albers等积投影(比如EPSG:102025),再进行相交和面积加权计算,这样统计结果更可靠。
4. 基于Python的批处理与进阶分析框架
4.1 用GeoPandas批量处理Shp转Excel长表
拿到Shp后如果需要转成Excel长表,按照GeoPandas可以写一个通用模板:
import geopandas as gpd import pandas as pd gdf = gpd.read_file("humi_1980_2024.shp") id_cols = ["省代码", "市代码", "县代码", "省", "市", "县"] date_cols = [c for c in gdf.columns if c.startswith("humi_")] melted = gdf[id_cols + date_cols].melt(id_vars=id_cols, var_name="字段", value_name="相对湿度") melted["日期"] = melted["字段"].str.replace("humi_", "") melted["日期"] = pd.to_datetime(melted["日期"], format="%Y%m%d") melted = melted.drop(columns=["字段"]).dropna(subset=["相对湿度"]) melted.to_excel("相对湿度_逐日_长表.xlsx", index=False)这段代码的要点是:先用melt把宽表变成窄表,再把日期字段解析出来。实际测试中,44年数据、县级面有2800多条记录,宽表16000多列,运行时间大约一分半,完全可接受。
4.2 多文件批量合并与加速技巧
如果你的数据是按年份拆分成多个Excel文件,或者你需要从多个分片里提取指定年份数,批量合并时我会推荐这样的方式:
import glob files = glob.glob("humidity_*.xlsx") frames = [] for f in files: part = pd.read_excel(f, dtype={"县代码": str}) frames.append(part) df = pd.concat(frames, ignore_index=True) df = df.drop_duplicates(subset=["县代码", "日期"])这里的drop_duplicates很重要,因为不同分片文件之间可能重叠时间范围,如果直接合并会造成重复计数。用subset去掉重复观测可以保证时间序列干净。
对于更大规模的分析,我建议用Parquet格式作为中间存储,读写速度比Excel快5-10倍。一次转换之后,后续所有数据加载都从Parquet读取,体验提升明显。
4.3 用统计方法快速识别数据质量问题
拿到时间序列后,除了前面提到的缺失值和异常值检查,我还会做一道更有力的检验:跳变检测。相对湿度是一个连续变化的气象要素,相邻两天之间不应该出现剧烈突变(除非有极端天气系统过境,但发生率也很低)。如果某一天的数据与前后日的差值显著超过40个百分点,就需要重点怀疑该日该区域是插值异常还是原始值伪造。
df["delta"] = df.groupby("县代码")["相对湿度"].diff() bad = df[df["delta"].abs() > 40]对这部分异常记录我会单独做可视化确认。曾经在一次数据处理中,通过跳变检测发现某县部分年份数据存在周期性错位——数据整体提前或延后一天,校正后与站点观测值的一致性明显提高。
5. 踩坑记录与常见问题排查
5.1 行政区划变更带来的匹配风险
我国县级行政区划一直在调整,撤县设区、合并拆分、新设开发区这类情况并不少见。1980年的县级边界与2024年的县级边界并不完全对应。如果你拿这套湿度数据去匹配1980年代的历史县域边界,很可能出现代码不匹配或者面形状差异。
我的建议是:在分析中尽量以研究期内最新不变化的一级行政区划为准,把历史数据全部归档到当前代码体系下。如果涉及历史特定区划,比如原某县已拆分为两个区,就需要根据面积权重自己拆分数据,不要直接用现在的县域代码去回溯替代。
5.2 天气系统的不连续性导致数据空间分布跳跃
相对湿度与气温、降水不同,它在空间上往往不是特别平滑,尤其是夏季对流性降水影响下,湿度场会出现明显的局地性。这意味着如果你在某个时间切片上做县级空间插值,生成一张平滑的连续表面,很可能会把真实的湿度边界抹掉。
我做了一次全国7月平均湿度制图,看到某些相邻县的湿度差值超过15个百分点,一开始怀疑是数据质量有问题,后来查看那几天的天气图才发现,正是由于局地强降雨和云系分布不均导致的结果。所以遇到这种情况不要急着当异常值剔除,先结合降水数据复核。
5.3 与气象站点观测值的融合思路
再分析数据集虽然有长序列、全覆盖的优势,但毕竟不是实测站点观测。我通常的做法是:用国家气象站点的观测值做双线性插值或反距离权重插值,再与这套数据做残差校正。方法很简单,先用气象站实测值减去数据集在站点的值,得到残差面,再把残差面叠加回原数据,完成数据同化。这种处理能兼顾数据集的广覆盖与站点的准确性。
至于融合效果,在丘陵、山区站点稀疏的区域提升最明显,能让逐日平均湿度的均方根误差降低两到三个百分点。注意不要用单一站点检验全区域表现,多站点交叉验证是基本操作。
5.4 数据使用中的版权与引用注意
这类会员专享数据一般只授权研究或分析使用,不建议直接对外再分发。如果你发表论文或报告,除了引用数据来源,还要写清楚数据处理的详细流程,包括降尺度方案、面积加权方法和质量控制阈值,这样可以方便同行复现,也是对自己工作负责。
6. 基于数据集的多种分析实战案例
6.1 县域尺度相对湿度变化趋势计算
做气候变化区域响应分析时,我最常做的一个操作是计算每个县的相对湿度变化趋势(单位:% / 10年)。用线性回归对逐日湿度序列做趋势线,再按季节拆分,能看到春夏季湿润化与秋冬季干燥化是否同期发生。
实际操作中我习惯把数据按年份算年平均值,再对年均值序列做统计检验。这样能避免逐日自相关带来的趋势显著性虚高。分析结果表明,在某地区部分县域的夏季相对湿度以每十年1到2个百分点的速率增加,这个信号与该区域的降水带北移相互印证,对农业生产布局很有参考价值。
6.2 用GIS做湿度分带与热区识别
空间分析中很实用的一项技能是“相对湿度分带”。基于多年平均湿度和变异系数,可以把县域划分为“稳定湿润区”“波动湿润区”“半干旱区”“干燥区”等类型。这一分类结果在农业保险定价和农作物品种布局研究里有用。
我通常用两项指标做二维分类:多年平均湿度决定干湿属性,湿度年际波动决定稳定性。在Arcmap或QGIS里分别渲染两个指标,再叠加生成组合图,非常直观。
6.3 建筑防潮设计重现期估算
在建筑设计行业,防潮设计需要知道当地极端高湿事件的发生概率。相对湿度超过80%且持续3天以上的天气过程,是地下室和墙体防潮设计关注的核心情景。
我把44年逐日序列按县统计每年出现的连续高湿事件次数,再用极端值分布拟合其重现期,输出10年一遇、50年一遇的高湿连续天数参考值。这类结果用来指导建筑设计非常直观。需要注意的是数据里的湿度值代表县域平均湿度,具体建筑微环境还需考虑朝向、通风和邻水条件,不能直接套用。
7. 个人经验总结与操作建议
这套数据我用下来最大的感受是:它的价值不仅在于数据本身,更在于能让你用44年的“上帝视角”看待中国各地湿度的命脉变化。但越是好用的数据,越需要科学、谨慎地处理。
我个人的建议是,先把数据完整读一遍,做全面的质量体检,再决定用长表还是宽表,用Shp还是Exce,这能避免在分析后期才发现数据口径不对的尴尬。处理代码要保留好,每一步中间文件也建议留存,因为后面对应审稿人或者业务复查时,能快速回溯结论的可信度。
最后给大家一个实用技巧:如果你要把这套数据接入一个更大的业务流程,比如农业保险精算或者健康预警系统,建议做一份“数据字典”,把字段含义、单位、坐标系、汇总方法、异常校正记录全部写清楚。这份文档的价值,有时候甚至比数据本身更重要。项目做完之后,交接给其他同事时,有这份字典会顺畅得多,踩过的坑也不至于再踩一遍。