国家级地面气象站日值数据集V3.0:处理与气候趋势分析实战

国家级地面气象站日值数据集V3.0:处理与气候趋势分析实战 做气候变化、农业气象、可再生能源评估的朋友十有八九绕不开“中国国家级地面气象站基本气象要素日值数据集(V3.0)”这套数据。它是目前国内公开渠道里覆盖站点最全、时间序列最长、要素最丰富的国家级地面气象日值资料之一由气象主管部门统一整编发布在很多科研论文和工程报告里都能看到它的身影。我早些年在做区域气候趋势分析和光伏资源评估时几乎天天和它打交道从最初对着数据说明文档一头雾水到后来能熟练地把几十个站点的几十万条记录清洗、质控、建模型中间踩了不少坑。这篇就把我对这套数据的理解和实操经验梳理一遍希望能帮你少走弯路。这套数据到底能做什么简单说它提供了全国两千多个国家级地面气象观测站从建站至今的逐日气象要素包括气温、降水、气压、湿度、风、日照、蒸发、积雪等几十项指标时间跨度从1951年前后一直到最近年份是做气候统计分析、极端天气事件研究、建筑节能设计、农业区划、新能源选址等工作的基础数据源。凡是需要“长时间序列、空间覆盖广、要素齐全”的气象基础资料基本都能从这套数据里找到答案。适合气象相关专业的学生、科研院所的研究人员、数据工程师以及从事农业、能源、交通、规划等行业的从业者参考使用。1. 数据集总体认知与版本沿革1.1 V3.0 解决了什么问题国内地面气象观测数据最早是纸面记录后来逐步电子化。早期版本的数据文件格式多样、质量标记不统一、要素命名混乱同一要素在不同年代可能是不同单位、不同观测时次用起来非常痛苦。V3.0版本就是在这个背景下推出的它把历史资料重新整编统一了文件格式、统一了要素编码、统一了质量控制标识并修正了一批早期记录中的明显错误。我印象最深的一点是旧版本里降水量单位不统一有的站点用0.1mm有的用1mm混在一起做统计会直接产出错误结果。V3.0把所有要素的单位和缩放系数都做了统一约定虽然格式说明读起来有点绕但至少不会再出现“数据本身有歧义”的问题。V3.0的站点规模大概在2400个左右覆盖了国家级基准站、基本站和一般站。基准站承担长期气候监测任务观测要素最全、资料连续性最好基本从20世纪50年代就开始积累数据一般站是后来加密布设的资料开始时间相对较晚部分站点可能只有近二三十年记录。做长时间序列研究时优先选基准站如果做空间插值或区域网格化则需要把三类站点都纳入。1.2 版本演进背后的数据治理思路V3.0不是简单把旧数据换个壳子背后其实是一套数据治理的思路。它把“观测原始值”和“质量控制结果”分开存储每个要素旁边都带一个质量控制标识码用户可以根据研究需要自行决定用哪种质量级别的数据。这比旧版本直接把错误数据删掉、不留痕迹的做法科学得多——至少你知道这个位置的数据出过问题而不是把它当成一个正常的缺测。从1950年代到2010年代中国地面气象观测经历了从人工观测到自动观测的重大转变。人工观测时代的日照、蒸发、积雪等要素靠人眼读数误差较大自动观测时代数据分辨率提高了但传感器故障、结冰、大风等也会产生更多异常值。V3.0在整编时对这两类数据做了衔接处理并统一标记了质量控制结果。这个衔接本身并不完美比如自动站和人工站交替期间的记录可能会有细微的系统性偏差但至少V3.0已经把这些元信息都列了出来使用者可以通过时间序列的突变点检测来识别和修正。2. 核心字段与数据格式深度解析2.1 文件结构与要素字段清单V3.0数据按站点组织每个站点一个独立文本文件文件名为站点区号加后缀。数据内容按“年-月-日”逐行排放每行包含几十个字段字段之间用空格分隔。我第一次拿到数据时打开文件看到密密麻麻的数字第一反应是“这玩意儿得靠程序处理”确实如此手工根本没法操作。以温度相关字段为例常见字段包括字段缩写含义单位原始值缩放Station_Id区站号无Station_Name站名无Lat / Lon / Alt纬度 / 经度 / 海拔度 / 度 / 米Year / Mon / Day年 / 月 / 日无TEM_Avg日平均气温0.1℃TEM_Max日最高气温0.1℃TEM_Min日最低气温0.1℃TEM_Max_Time最高气温出现时次时次编码PRE_Time_202020-20时降水量0.1mmPRS_Avg日平均本站气压0.1hPaRHU_Avg日平均相对湿度1%WIN_Avg日平均风速0.1m/sWIN_D_Max最大风速对应风向度EVP小型蒸发量0.1mmSSD日照时数0.1hGSD积雪深度0.1cm这里有一个特别容易出错的点很多要素的原始值都做了缩放气温实际值是327要除以10得到32.7℃降水实际值是56除以10得到5.6mm风速实际值是45除以10得到4.5m/s。但也有像相对湿度这样不做缩放的原始值就是百分比。如果不仔细看说明文档把缩放系数搞错统计结果会差出10倍。这是新手最容易踩的一个坑。2.2 特殊数值约定与质量控制标识V3.0里有一批特殊数值用于表示缺测、无观测任务、微量降水等状态。这些数字不是真实观测值参与计算前必须处理。常见特殊值如下特殊值含义32766缺测32744无观测任务31392降水微量小于0.05mm32700数据可疑但无法更正32755仪器故障32722因天气原因未观测以降水为例31392代表“有降水现象但降水量不足0.05mm”通常当作0处理但在统计降水日数时应该算作一个雨日。如果直接用原始值参与平均那这个31392会让站点年均降水量凭空多出几百毫米属于严重的逻辑错误。气温的特殊值基本都是32766缺测处理起来相对简单直接剔除或插补即可。质量控制标识QCFlag是V3.0的另一个关键字段。每个要素后面通常跟着一个两位数或一位数的质控码含义大致是0数据正确1数据可疑需要人工复核2数据错误已经更正或剔除8数据缺测或无观测9数据未经过质量控制我个人的建议是做趋势分析或气候平均时只保留质控码为0的数据做极端事件统计时可以把质控码为1的数据也纳入但需要用其他方法交叉验证。直接忽略质控码把所有数据都拿来算结果通常也不会差太多但在个别站点、个别年代可能会有明显异常值混入影响结论可信度。3. 数据获取与预处理实操3.1 获取途径与授权说明这套数据目前在国内通过气象数据共享服务渠道提供申请获取一般单位和高校科研人员都可以申请。拿到手的是一个压缩包里面包含数据文件、说明文档README、站点元数据表。我建议第一步不是急着写代码而是把README完整读一遍尤其是“数据说明”“质量控制说明”“更新说明”这几节里面会讲清楚每个字段的精确定义和格式版本。站点元数据表也很重要它记录了每个站点的区站号、站名、经纬度、海拔、建站时间、迁站记录等。做时空分析时这些信息直接决定站点是否可用、数据是否连续。比如某个站点在2005年发生过迁站新旧站址海拔差了200米那这个站点的气温时间序列在2005年前后可能会有一个明显跳变不是气候变化造成的而是观测环境变了。如果不查元数据表直接用这个序列做趋势分析结果会失真。3.2 Python读取与清洗的标准流程我日常处理这套数据用的主要工具是Python配合pandas和numpy。先写一个通用的读取函数把文本文件解析成DataFrame再做特殊值替换和质控过滤。这里我给出一套可以直接参考的代码框架。import pandas as pd import numpy as np # 根据实际文件字段个数和名称调整 column_names [ Station_Id, Station_Name, Lat, Lon, Alt, Year, Mon, Day, TEM_Avg, TEM_Max, TEM_Min, TEM_Max_Time, PRE_Time_2020, PRS_Avg, RHU_Avg, WIN_Avg, WIN_D_Max, EVP, SSD, GSD ] df pd.read_csv( station_xxxxx.txt, sepr\s, headerNone, namescolumn_names, na_values[32766, 32744, 32700, 32755, 32722], encodinggbk ) # 处理微量降水先替换为0另建一列标记是否为微量降水日 df[PRE_Is_Trace] df[PRE_Time_2020] 31392 df[PRE_Time_2020] df[PRE_Time_2020].replace(31392, 0) # 处理缩放系数除以10还原真实值 scale_cols [TEM_Avg, TEM_Max, TEM_Min, PRE_Time_2020, PRS_Avg, WIN_Avg, EVP, SSD, GSD] for col in scale_cols: df[col] pd.to_numeric(df[col], errorscoerce) / 10.0 # 构造日期列 df[Date] pd.to_datetime(df[[Year, Mon, Day]]) # 按年度聚合计算年均气温和年降水量 df[Year_only] df[Date].dt.year yearly df.groupby(Year_only).agg( tas_avg(TEM_Avg, mean), tas_max(TEM_Max, mean), tas_min(TEM_Min, mean), pre_sum(PRE_Time_2020, sum) )这段代码解决了三个核心问题批量读取时把特殊值统一转成NaN、微量元素单独标记、缩放系数统一换算。代码运行之后得到的是干净的、可用于统计建模的年值序列。值得提醒的是先把站点元数据合并进来再做分析。比如你要研究某个区域的平均气温变化需要把区域内多个站点的数据拼接起来按经纬度做区域平均。如果某个站点经纬度写错了或者海拔和实际不符结果会误导后续的空间插值。所以我一般会先用散点图检查站点位置分布确认没有明显的坐标漂移。4. 常见问题与排查技巧实录4.1 问题速查表下面是我在实际使用中整理的常见问题清单几乎每次培训或交流都会有人问到。问题现象可能原因处理方法降水总量异常偏大微量降水特殊值31392未处理替换为0或单独标记气温序列在某个年份突然跳变站点迁站或观测仪器更换查元数据表分段处理部分字段大量出现32766该要素在该时段无观测任务按缺测处理不参与统计数据文件读取乱码编码不是UTF-8而是GBK用encodinggbk读取风速序列在夜间出现连续0值风速低于启动风速静风保留0值不要剔除日照时数超过理论日照时数数据格式或质控异常用天文日照时数做上限校验不同站点同一日期时间温度差异过大站点海拔或局地环境差异结合海拔梯度检验4.2 最值得警惕的三个大坑第一个坑是台站迁址。中国国家级站点在几十年的运行中不少都经历过迁址有的从城区迁到郊区有的从低海拔迁到高海拔。迁址之后气温、风速、湿度都会出现系统性的变化。我有一个项目里分析某城市热岛效应结果发现城市站和郊区的温差在逐年缩小一开始以为是热岛减弱后来查元数据才发现是城市站迁到了更远的郊区。这个教训让我此后分析任何站点序列前都会先画一张站点位置和海拔的核对图并检查序列中是否存在明显的不连续点。第二个坑是自动站与人工站的数据衔接。2010年前后是自动站全面替代人工站的过渡期。人工观测的日照时数用的是暗筒式日照计自动站用的是直接辐射传感器两者工作原理不同在阴天、低角度太阳辐射条件下会有系统差异。所以做日照时数趋势分析时要留意2010年前后的跳变点。气温和降水相对好一些但风速也存在仪器换型导致的偏差尤其是弱风条件下的记录差异。第三个坑是极端值的合理性判断。V3.0虽然做了质量控制但个别站点的极端记录仍可能有问题。比如降水量日值超过300mm在东部沿海或台风影响区是可能的但如果在西北干旱区出现就要怀疑数据质量。做极端事件研究时我一般会加一道气候学界限检查比如日降水量不能超过800mm日最高气温不能超过50℃日最低气温不能低于-55℃超出这些范围的记录单独挑出来复核。4.3 插补方法的选择建议时间序列中缺测不可避免。如果只是做年值或季值统计缺测比例低于10%时直接剔除对应年份即可。但要做逐日序列的连续分析比如生长季积温、连续干旱日数就需要插补。常用的插补方法包括邻近站点回归插补、气候平均值替换、时间序列线性插值。我个人的经验是对气温类要素邻近站点回归插补效果最好因为气温的空间相关性很强几十公里范围内的站点日值相关系数通常在0.9以上对降水类要素任何插补方法都容易失真因为降水是间歇性过程空间变率大最好是用邻站当日的“有雨/无雨”状态做逻辑推断再结合距离权重估算雨量。不要用简单的线性插值去补降水日值那会把降水过程抹平导致连续干期被低估。5. 实战案例利用该数据集做一次区域气候趋势分析5.1 分析流程设计假设我们要研究某个区域过去60年的气温和降水演变趋势完整的分析流程大致如下第一步从数据集中筛选出区域内全部站点按站点元数据剔除数据质量差、观测年限不足30年的站点。做趋势分析时站点至少要有30年连续观测记录否则趋势估计的置信区间太宽没有实际意义。第二步读取并清洗数据把特殊值、质控标识、缩放系数都处理好得到干净的逐日序列。第三步将逐日数据聚合到年尺度计算年均气温、年降水量、极端高温日数、极端降水日数等指标。第四步对每个站点的年值序列做线性趋势估计用Mann-Kendall检验判断趋势显著性。线性趋势用最小二乘法即可但要注意自相关性对显著性检验的影响气温序列通常是正自相关的会虚增自由度导致显著性被高估。更稳妥的做法是做预白化处理或者用考虑自相关的修正检验。第五步把单站趋势插值到空间网格或者做区域平均趋势。区域平均要用面积加权或经纬度加权不能用简单算术平均因为站点分布不均匀东部密西部疏简单平均会高估东部站点的影响。5.2 关键代码示例区域平均气温趋势的代码可以这样组织from scipy import stats def calc_trend(series): # 剔除缺测年份 df_valid series.dropna() if len(df_valid) 30: return np.nan, np.nan, np.nan, len(df_valid) years df_valid.index.values.astype(float) values df_valid.values.astype(float) slope, intercept, r_value, p_value, std_err stats.linregress(years, values) return slope, p_value, r_value, len(df_valid) # 对区域内所有站点计算年均气温趋势 trend_results {} for stid, sub_df in data_grouped: yearly_temp sub_df.groupby(Year_only)[TEM_Avg].mean() slope, p_value, r_value, n calc_trend(yearly_temp) trend_results[stid] { slope: slope, p_value: p_value, r_value: r_value, n: n, }跑完这个脚本后会得到每个站点的气温倾向率单位通常是℃/10年以及对应的P值。把所有站点结果叠加在地图上就能直观看出哪些区域升温明显、哪些区域不显著。降水趋势也同理但降水年际变率大趋势通常不容易通过显著性检验这种情况下要重点看极端降水事件频率的变化而不是平均值变化。5.3 结果解读时要注意的细节趋势分析的结果不能只看斜率数值还要看空间一致性。如果相邻站点之间的趋势方向相反且都显著首先要怀疑站点数据质量或迁站影响而不是急着下气候变化的结论。区域气候信号往往是空间连续的偶尔有个别站点表现特异多和数据连续性有关。还有一种情况是序列的“端点效应”。如果研究时段正好从某次强厄尔尼诺年或强拉尼娜年开始首尾年份的异常值会显著影响线性趋势的斜率。我在分析2000-2020年降水趋势时就遇到过这种情况2000年是偏干年份2020年是偏湿年份拟合出来的上升趋势明显偏大。解决方法是多算几个子时段做敏感性分析比如1951-2020、1961-2020、1971-2020、1981-2020看趋势是否稳定。如果趋势随起止年份变化很大那结论的稳健性就要打折扣。6. 数据集的局限性认识与适用边界6.1 站点分布与空间代表性V3.0虽然覆盖全国两千多个站点但站点分布极不均匀。东部平原地区站点密度高西部高原和沙漠地区站点稀少青藏高原腹地可能几百公里才有一个站。做全国尺度的空间分析时这种不均匀分布会带来系统性偏差。比如计算全国平均气温时如果不对站点做加权处理西部稀疏站点的影响会被弱化而东部密集站点的影响被放大得到的平均值偏向东部气候特征。解决的办法有几条一是做区域平均时按网格面积加权把站点气温插值到规则网格上再计算面积平均二是用经纬度和海拔做多元回归把站点观测值订正到统一参考面上三是直接使用气象部门发布的网格化数据集它本身也是基于站点数据插值生产的但经过了更严格的质量控制和地形订正。网格化数据在空间连续性上更有优势但在逐日极端值和单站准确性上还是原始站点数据更可靠。6.2 要素覆盖的短板V3.0的核心要素是气温、降水、气压、湿度、风、日照、蒸发、积雪基本覆盖了传统气候统计的需求。但近些年比较热门的辐射四分量、土壤温湿度、地表温度、CO2浓度等要素这套数据里没有。做地表能量平衡、陆气相互作用、碳循环研究时需要另外申请辐射观测数据和涡动相关通量数据。另外这套数据的“日值”是24小时累积或平均的概念无法还原日内变化过程。研究极端降水的小时尺度演变、气温日较差的变化机理、城市热岛的昼夜差异需要更精细的逐小时或逐分钟数据。日值数据适合做气候平均、趋势、频率分析不适合做过程机制研究这一点要提前有预期。6.3 历史数据观测方式差异1950年代建站初期观测仪器简陋、观测时次少、站址变更频繁数据质量与当代不可同日而语。V3.0虽然做了质量控制但早期数据中仍可能存在一些系统误差。比如1950-1960年代的气温观测使用百叶箱和通风干湿表日平均气温的计算方法是多次观测的简单平均而现在自动站的日平均算法则基于24小时逐分钟数据两者在某些天气条件下会有差异。我通常的做法是做长期趋势研究时对早期数据保持谨慎尽量把分析重点放在1961年或1971年以后。世界气象组织推荐的“气候标准时段”是1961-1990和1991-2020这种标准时段的选择本身就是为了避开早期观测不稳定和站点稀疏的问题。如果不是专门研究1950年代的极端事件建议直接用标准时段做基准期。7. 沿着这套数据继续扩展的思路7.1 与再分析资料的交叉验证站点观测数据是“真值”参考但在空间连续性和覆盖度上不如再分析资料。把V3.0站点数据与ERA5、JRA-55等再分析资料做对比可以评估再分析资料在区域的适用性。我做过一个测试用V3.0站点气温和ERA5格点气温做逐日对比发现中国东部两者的相关系数超过0.98但在西部复杂地形区偏差明显增大冬季尤其严重。这个对比结论对后续使用再分析资料做驱动场、做气候模拟评估都非常有价值。7.2 与卫星遥感数据结合对于降水站点数据与卫星降水产品如GPM、TRMM的融合是当前的热门方向。卫星产品空间覆盖广、时效快但偏差大站点数据精度高、但空间代表性有限。用V3.0站点降水做偏差订正和验证是卫星降水产品落地应用的关键一步。我曾经参与过一个山洪预警项目核心工作就是每天用约800个站点的小时降水数据去订正雷达定量降水估测站点密度不够时预警准确率明显下滑。7.3 建立个人气象数据库如果你长期从事气候相关研究建议把V3.0清洗后的数据存成统一的格式比如Parquet或NetCDF并构建一个简单的元数据索引。这样后续每次做分析不需要重新走一遍读取、清洗、质控的流程省下大量时间。我自己的经验是把清洗脚本和原始数据分开存放脚本加好注释数据版本做好记录几年后回头再找数据时能节省很多精力。写在最后的一点心得从拿到V3.0原始数据到能熟练处理我大概经历了两周左右的阵痛期大部分时间都花在理解格式、排查异常值、调试代码上。回头看这套数据集本身做得已经相当规范真正的难点往往在于使用者是否理解气象观测的基本逻辑什么是缺测、什么是微量、什么是质控、什么是迁移影响。数据处理只是手段理解数据背后的物理意义才是根本。建议你在动手写第一行代码之前先花半天时间把数据集说明文档从头到尾读一遍把每个字段的含义、单位、特殊值标记搞清楚。这半天看起来是“浪费”实际上能帮你省掉后面数倍的时间。V3.0是一套值得长期投入精力去熟悉的基础资料把它用好、用透后续很多气象、农业、能源相关的研究和工作都会顺畅很多。