资讯动态

全球2m气温数据集(1940-2024)实战:处理技巧与踩坑总结

发布时间:2026/10/21 3:31:52 来源:尧图企业网站定制
做气候数据分析的人应该都有过这种尴尬项目要求写一份从1940年到现在的气温变化评估我去翻本地观测站记录不是断档就是站点迁移好不容易凑齐一段还发现观测规范和单位前后不一致。后来我把目光转向了公开的全球2m气温数据集1940—2024——这是一套把整个地球按规则格网切好、逐小时给出近地面气温的历史序列。它解决的就是“时间段连续、空间覆盖完整”这个核心痛点。适合做区域气候背景分析、农业积温计算、建筑能耗预测以及给论文或报告提供基准图层的同学参考。这篇文章我不打算复述官方文档只讲我拿这套数据落地时的真实操作、踩坑和代码希望对正在琢磨这套数据的人有点用。1. 先补一堂基础课2m气温到底是不是“地表温度”1.1 为什么气象上把温度测在2米而不是地表很多人第一次打开数据文件看到“2m temperature”第一反应是“这不就是地面温度吗”我最初也这么以为后来拿实测校正时发现偏差非常大才去翻资料补课。所谓2m气温指的是距离地面两米高度处、通常由气象站百叶箱内的温度传感器测得的空气温度。气象观测规范之所以把传感器架在离地1.5到2米的位置是因为这个高度基本避开了地表白天强辐射加热和夜间辐射冷却造成的剧烈温度梯度。赤道附近的正午地面可以比两米处高出十几摄氏度但站在树下的人感受到的其实是2米左右的空气温度。所以2m气温对绝大多数生物活动、人居环境、农业生长、建筑能耗来说才是最直接的“体感温度”而不是地表皮肤温度。这一点是整个数据集使用的逻辑起点。1.2 再分析资料里2m气温不是直接“测”出来的这套1940—2024的全球数据本质上不是某个气象站连续测量的结果而是将历史观测资料送入数值天气预报模型利用数据同化技术把观测和模式背景场合并后产生的一套“再分析”格点产品。所谓再分析就是用一个固定的数据同化系统把过去几十年能搜集到的地面站、探空、卫星观测都重新“消化”一遍避免因为模式版本升级造成人为的不连续。模式内部实际计算的是数百米到几公里高度的三维大气状态2m气温并不是直接预报量而是在每个网格点上根据最低模式层的温度、湿度、风速以及地表温度用类似近地层廓线外推的方法诊断出来的。你可以把它理解成模式先算出紧贴地面的那一层空气的状态再用一套长时间积累的物理经验公式把这层状态“翻译”到两米高度。因此它天然带有一定模式误差尤其在边界层很稳定、逆温很强的夜间。1.3 和观测站气温差别主要差在“空间观”而非“尺子”既然都是2米左右高度的气温为什么单站观测和格点值常常对不上第一个原因不是数据“错”而是两者代表的空间范围不同。气象站测的是站点周围几十米、顶多几百米的局地空气温度而再分析数据里一个格点代表的是几十到上百公里范围的平均结果。第二个原因是地形和下垫面的差异被抹平了一个格点内部可能有山地、谷地、水体实际气温分布很不均匀格点值只能代表平均状态。第三个原因是时间上的平滑逐小时的再分析输出虽然已经是高频输出但仍然比站点瞬时观测平滑。所以我一再提醒自己用这份2m气温数据集做区域平均、年代际趋势是合适的但拿它和一个具体站点做逐小时强行对标需要先接受空间代表性误差较大这个事实。先把这个底层认知立住后面的操作才不会一路跑偏。2. 拿到文件先别急着画图数据格式、单位和坐标的几条硬规则2.1 我拿到的文件长什么样我通常拿到的分发文件是NetCDF格式有的服务商也提供GRIB但NetCDF在Python生态里最友好。打开数据后第一件事不是画图而是弄清楚变量维度。最常见结构是经度、纬度、时间三个坐标再加上气温变量一般叫t2m单位是开尔文。水平分辨率通常是0.25°×0.25°全球大概是1440×721个格点时间分辨率有逐小时的也有聚合好的逐日和逐月产品。在使用前我会先用一行代码检查基本信息而不是盲猜import xarray as xr ds xr.open_dataset(2m_temperature_1940_2024.nc) print(ds) print(ds[t2m].attrs) # 查看单位、long_name、坐标轴描述这一步能看到变量单位、缺失值标记、坐标是递增还是递减。很多人在这一步省了时间后边单位换算和坐标翻转就会花更多时间。2.2 时间、纬度、经度最容易搞错的三件事第一件是时间基准。再分析产品几乎所有输出都使用世界时UTC哪怕你只研究国内某一片区域文件里的时间戳也都是UTC。如果直接用当地时间去匹配站点日最高气温会因为时区导致日界对不上所以我拿到数据后第一件事是把时间索引转换成目标时区比如ds[time] ds[time] - pd.Timedelta(hours8)东八区这样处理最省事。第二件是纬度排序。有些版本纬度从北到南递减有些从南到北递增用sel(latitudelat, methodnearest)之前最好先sortby(latitude)否则很容易选到对冲的格点。第三件是经度范围。数据文件里的经度可能是0到360也可能-180到180。做区域裁剪时要先确认如果研究区域接近0度经线或180度经线裁剪逻辑要单独写不能直接笼统判断。2.3 打开文件后的第一段处理代码我这里给出最通用的“开门三板斧”转摄氏度、裁剪到目标区域、落地为一个临时NetCDF。你不一定照抄但建议把这套处理沉淀成自己的函数因为每次分析都会用到。import xarray as xr import numpy as np ds xr.open_dataset(2m_temperature_1940_2024.nc) # 单位转换很多产品是开尔文转成摄氏度跟观测对比更方便 ds[t2m_c] ds[t2m] - 273.15 # 统一经度为-180到180 if ds.longitude.max() 180: ds ds.assign_coords(longitude(((ds.longitude 180) % 360) - 180)).sortby(longitude) # 裁剪一个示例区域请替换成你的研究区边界 region ds.sel(latitudeslice(30, 45), longitudeslice(105, 120)) region.to_netcdf(region_2m_temperature.nc)这段代码本身没什么高深之处但它能把你从“文件很大、CPU被吃满”的焦虑里救出来——先把原始文件读一遍确认坐标和单位再裁剪而不是每次都全量加载。至于区域经纬度这里的30、45、105、120只是示例不代表任何特定含义。3. 按你的研究区切数据站点提取、区域平均和重采样的一次通关3.1 站点提取最近格点还是插值做站点级验证时需要把格点数据“落到”站点位置上。最简单的做法是sel(latitudelat, longitudelon, methodnearest)直接取最近网格。这在网格分辨率为0.25度时最坏会引入约0.125度的定位误差换算到地面差不多十几公里。对大多数气候分析这可以接受但如果站点恰好在山脚、河边一个网格之差可能带来好几摄氏度的差异。所以我在正式研究中更倾向于双线性插值取站点周围四个格点按距离加权平均。xarray的interp方法直接支持site_temp ds[t2m_c].interp( latitudelat, longitudelon, methodlinear )注意interp要求经纬度坐标严格递增如果报错先执行一句ds ds.sortby(latitude).sortby(longitude)。插值不会创造奇迹但在山区、海岛这些下垫面变化剧烈的地方稳定性明显优于最近邻。如果你的研究区跨过0度经线最好先做经度平移再插值不然四角插值的权重会乱。3.2 区域平均别忘记纬度加权区域平均听起来简单框一个经纬度范围然后mean()但这里藏着一个几何问题地球表面每个等经纬度格子的实际面积并不相等纬度越高单个格点代表的面积越小。如果直接对格点值取算术平均高纬度地区会被过度代表。正确的做法是给每个格点乘cos(latitude)权重后再平均。尤其做跨纬度带比如20度到50度的多年平均时不加权重和加权的结果能差出0.3到0.5度这对趋势分析已经不可忽视。下面这段是处理模板weights np.cos(np.deg2rad(ds[latitude])) region_weighted_mean ds[t2m_c].weighted(weights).mean(dim[latitude, longitude])如果是很小的研究区比如一个城市或者一个流域经纬度跨度只有一两度加不加权差异不大我一般会偷懒不加权但写进报告时仍然会声明“区域面积平均采用余弦纬度加权”。3.3 时间重采样从逐小时到日均、月均的正确姿势这套数据如果是逐小时分辨率的做气候统计之前通常要先重采样到日或月。重采样最常被问到的问题是日平均到底用哪些时次如果数据是0点到23点共24小时直接用resample(time1D).mean()得到的是UTC日平均。要得到地方太阳日的平均最好先做时区或经度换算再用当地时间分组。比如东八区可以用ds[t2m_c].resample(time1D, offset8h).mean()。另外计算日最高、最低气温时不是简单对24小时求max和min而是要检查有没有跨日界。如果站点观测用的是北京时间20时日界而再分析文件是UTC日界两者统计的“一天”根本不一样。这一点在对比时尤其阴险我吃过一次亏排查了半天偏差最后发现只是日界错位了8小时。3.4 导出成CSV时把元数据一起写进去我见过不少分析师从格点数据里提出一条站点的逐小时序列然后直接to_csv()存成一个只有时间和气温的表格三个月后自己都忘了这列气温是什么单位、从哪个格点来的。我现在导出时会强制在文件头写明变量名、经纬度、单位、时间基准和时间步长哪怕多几行注释也值得。一个可用的导出示例import pandas as pd ser region[t2m_c].sel(latitude30.5, longitude110.2).to_series().rename(t2m_celsius) df pd.DataFrame(ser) df.to_csv(site_t2m_1940_2024.csv, encodingutf-8-sig)如果你准备交给别人更要在文件名里包含t2m_degC_daily_1940-2024_regionX.csv这种格式而不是简单的data.csv。数据管理上的好习惯能省掉大量重复对账的功夫。4. 我在这套数据上踩过的五个坑每个都对应一个排查思路4.1 最早期年份的质量1940—1950年代不是“不能看”但要看仔细这套数据的时间跨度从1940年开始但再分析对早期年份的约束主要依赖地面观测卫星观测还没出现探空站点也少得多。所以1940—1950年代的同化质量整体比现代偏低尤其在海洋、极地和南半球模式误差会被放大。我做某区域长期趋势时发现如果从1940年开始做线性趋势斜率和从1960年开始做可以差出近一倍原因不是气候突变而是早期数据方差更大。现在我的处理习惯是把1940—1959单独作为一个“参考期”不直接参与回归如果必须使用完整序列至少把趋势显著性检验换成考虑异方差的方法并在图里标出早期数据的不确定性条带。4.2 海岸线与山地格点中心不代表地表真值再分析网格中心点落在海里但被标记为陆地格点的情况或者相反在海陆交界处非常普遍。只要网格中心一偏陆地上的站点就可能匹配到海洋性更强的格点导致冬季偏暖、夏季偏凉。山地更是重灾区一个0.25度格点内部高差可能超过1000米格点平均气温实际上对应的是该格点的“等效高度”而不是某个山腰站的观测高度。我的排查思路是每次匹配站点前先对比站点海拔和对应格点高程如果海拔差超过300米就先做温度垂直递减率订正通常取-0.65℃/100m或在近地面取-0.5℃否则偏差很难解释。4.3 极端温度被“抹平”热浪和寒潮研究要格外小心再分析产品本质上是模式输出模式对强烈天气过程的强度往往估计不足。日最高气温来自逐小时气温序列而这些逐小时值本身经过模式平滑热浪期间的极值经常低于站点实测2到4摄氏度个别强逆温夜里的最低气温也可能比实测低不少。有一次我拿数据识别热浪事件阈值设35度站点记录出现连续三天高温而格点数据只有第一天超过阈值。这说明用这套数据做绝对阈值判断不可靠更适合做相对阈值比如与当地气候态的百分位比较。如果必须做绝对阈值建议先用站点观测做分位数映射订正把格点累计分布和站点分布对齐再重新计算极值。4.4 单位、FillValue和缺测小事翻车最常见气温变量单位通常是开尔文我见过有人直接画图等值线全是几百还有文件会把无数据区域填成-32767或1e20如果没有查看_FillValue统计时会混入天文数字。xarray一般会把缺测自动显示为NaN但有些从GRIB转成NetCDF的文件并不那么可靠。我每次读取后会主动做一次清污比如temp ds[t2m].where(ds[t2m] 50) # 把低于50K的异常值剔除同理如果数据在网格边界出现规则形状的缺测要检查是不是经纬度裁剪的边界误差而不是数据本身有问题。这种“小事”往往浪费的时间最多因为错误数据画出来的图乍一看很正常。4.5 “站点值”和“格点值”直接对比会得出系统性偏差最后这个坑其实和基础认知有关。很多人把某个格点值拿去找同期站点值发现平均偏差有1到2度就认为数据不准。但实际上这种对比得到的偏差可以拆成三部分再分析本身的模式误差、站点局地环境影响、空间代表性误差。最后这部分往往占大头。举例来说一个位于河谷的站点冬季逆温频繁而周围格点平均海拔更低那么格点值大概率偏暖这不是站点错了也不是格点错了而是“点”和“面”在气候学上本来就不是同一类东西。我的处理办法是先做空间平均比如取站点周围3×3格点平均再对比并同时记录海拔差如果研究区域非常复杂宁可用高分辨率的局地气象数据做降尺度也不能硬上全球2m气温。坑典型现象排查思路早期年份质量差1940—1960趋势异常单独设参考期不用早期做趋势主结论海陆与地形失配站点与格点系统性偏差对比海拔做垂直递减订正极值被平滑热浪偏少、极值偏低改相对阈值或分位数映射订正单位与FillValue数值异常、统计污染读取后检查attrs主动where剔除点面对比直接对比RMSE很大3×3空间平均报告空间代表性误差5. 三个我用2m气温数据做过的项目场景5.1 农业热量资源积温和生长季长度在农业气候区划里≥10℃活动积温是最常用的热量指标之一。做法很简单先把逐小时数据重采样成日平均气温统计每年中日平均气温≥10℃的天数和这些天数的日均温累计值。要注意的是积温计算必须使用完整自然日不能把闰年2月漏掉也要规定好起始日期比如固定日期4月1日或第一次稳定通过10℃的日期。我用这套数据做某区域积温分布时发现1980年代和2020年代相比≥10℃积温的空间范围明显北移这个信号在站点资料里因为观测缺测反而不容易呈现。格点数据的价值就在这里它不怕站点换址、缺测能给出连续的空间场。5.2 建筑能耗采暖度日数和制冷度日数建筑能耗领域的经典参数是采暖度日数和制冷度日数。采暖度日数通常定义为日平均温度低于基准温度的差值累计比如18℃制冷度日数则是日平均温度高于26℃的差值累计。用2m气温逐时数据可以做得更细逐时温度可以计算采暖小时数而不只是日平均。我在某建筑能耗评估任务里用1940—2024年逐时2m气温计算了某地的采暖度日数逐年序列发现与站点结果整体一致而且因为格点数据覆盖连续能把过去缺失年份的能耗需求补齐。这类应用不需要特别高的极端值精度恰恰需要平稳连续的逐时序列这套数据非常契合。5.3 城市热浪相对阈值识别热浪没有全球统一标准常见定义是日最高气温≥35℃且持续3天但再分析对极值的平滑作用会低估热浪频率。我改用百分位定义取某个格点1961—1990年日最高气温的95百分位作为阈值连续3天超过阈值记为一次热浪事件。这样处理后再看趋势仍然能看到热浪次数在近20年明显增多。关键点在于阈值是自己用同一套数据算出来的系统性偏差会部分抵消所以得到的事件相对可靠不依赖绝对精度。如果你要做城市层面的热浪预警建议再用站点观测做偏差校正因为格点上的35℃和站点上的35℃物理意义不完全一样。6. 跟观测数据做一次“握手验证”质量评估的完整流程6.1 数据配对与时空匹配规则正式使用前我会抽出一部分站点做验证。流程是先把站点经纬度对齐到格点上优先选海拔差小于200米的配对时间上预留出边界缓冲比如站点是逐日数据就要求当天24小时完整不能只拿部分时次然后把站点日序列和格点日序列按日期对齐。这里需要特别注意站点数据的日界和文件的时间基准必须一致前面提过很多对不上的问题其实出在日界。再检查站点数据里有没有离群值比如气温跳变超过15度而相邻日正常通常直接剔除。6.2 三个统计指标和一个可视化质量评估至少要算三个指标平均偏差、均方根误差、皮尔逊相关系数。以我的经验这套2m气温数据集在大多数陆地区域的日平均气温偏差在±1℃以内均方根误差在2℃左右相关系数基本在0.95以上但在复杂山区均方根误差能接近4℃。把这些指标整理成表并标记样本量和时段比单独说“误差不大”有说服力得多。可视化上我常用散点密度图横轴是观测、纵轴是格点颜色表示点数密度如果散点整体在45度线以上说明有系统性暖偏差反之则偏冷。这种图一眼就能看出偏差形态也方便给合作者解释。6.3 结论表达和后续订正思路验证完成后不要只写“吻合较好”这一个结论。我一般会把结果区分为“系统性偏差”和“随机误差”。如果散点图显示系统性偏移可以用一元线性回归做订正T_obs a b * T_model把这组系数用到整个格点场注意订正系数本身带有空间区域性不能直接把某地的公式平移到另一区域。如果偏差主要是随机误差那说明模式与观测的差异来自未分辨的局地过程盲目订正反而可能破坏物理一致性。这类教训让我养成了习惯用数据前先问自己最终结论依赖的是绝对阈值、趋势还是空间分布不同依赖对数据质量的要求完全不一样。最后再分享一个小习惯我每次跑完上面这套流程都会把处理脚本和验证结果保存在同一个项目文件夹里文件的命名直接带上数据版本和时间范围。下次再有人问我“这套2m气温数据集能直接用吗”我可以打开验证记录告诉他“在日平均尺度上没问题极端事件要谨慎山区要修正”。数据用得好不好往往不取决于第一眼的新鲜感而是这些反复验证中攒下的判断。这套1940—2024的2m气温数据值得你花一个下午做同样的“握手测试”之后它才会成为你工具箱里真正可靠的那把尺子。

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

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

免费获取报价 →
↑