做全国尺度的土壤相关分析,最头疼的往往不是模型怎么跑,而是底图数据从哪来。要么是30米精度的局部产品,覆盖范围只有几个省;要么是1公里分辨率能覆盖全国,但栅格粗到只能看个大趋势,放进小流域就完全没法用。我第一次拿到这份中国土壤厚度栅格数据(90米分辨率,2010–2018年,基于高分辨率国家土壤信息格网,全国覆盖)时,第一反应是:终于有个能用、可下载、覆盖全国的中间尺度了。这份数据不是单纯一个tif文件那么简单,它背后牵扯到分辨率、时间标签、土壤属性定义、投影坐标系、NoData处理、与其它数据对齐等一系列问题。这篇文章就把我从下载到实际使用踩过的坑、查过的文档、总结出的经验全部倒出来,给正在找土壤数据做建模、做评价、做区划的GIS和土壤领域的朋友做个参考。无论你是刚入行的研究生,还是常年处理空间数据的工程师,这份数据都值得放进工具箱。
1. 数据源深挖:高分辨率国家土壤信息格网是怎么回事
1.1 这套数据是怎么生产出来的
先说结论:这份90米栅格不是“卫星拍出来的”,也不是每年重新测一遍的结果,而是基于国家层面多年积累的土壤调查资料,经过统一的标准化、空间化建模之后生成的格网产品。
我查过的资料和相关说明里,这类产品的底层逻辑通常是这样的:首先收集历史上大量土壤剖面点数据,包含每个剖面的分层厚度、质地、有机质含量等信息。然后把这些点数据作为“真值”,再叠加一系列环境协变量,比如地形坡度、坡向、高程、气候数据、母质类型、植被指数等,用机器学习或者地统计插值的办法,建立“环境变量→土壤属性”的预测模型。最后把这个模型应用到全国连续的栅格面上,得到每个像元的土壤属性估计值。高分辨率国家土壤信息格网这个体系,大致就是沿用了国际上SoilGrids这类产品的技术路线,只不过针对我国土壤调查数据特点做了本地化适配。
这意味着什么?意味着这份数据是“预测值”,而不是“实测值”。任何一个像元上的数值,都是模型推演出来的,精度取决于输入剖面的密度、环境协变量的质量以及模型本身的设定。这个认知特别重要,因为后面很多应用场景的选择——比如能不能用于小流域、能不能用于田块尺度,都受这个底层逻辑限制。
1.2 为什么90米分辨率是“甜点分辨率”
早期我常用1公里分辨率的土壤数据做全国尺度的生态评估,说实话,够用,但总觉得“肉不够细”。换到30米分辨率的数据,问题就来了:很多30米产品覆盖范围不全,且因为模型在细尺度上噪声放大,局部会出现非常突兀的极值,反而需要花大量时间去平滑和清洗。
90米这个尺度,是个很有意思的中间值。按面积算,一个像元是90×90 = 8100平方米,约合0.0081平方公里,比1公里栅格精细了约123倍,可以支撑县域、流域、省级甚至全国尺度的分析。同时,90米又足够“钝”,能把局部噪声抹掉一部分,不像30米那样敏感。我在做东北黑土区的厚度空间分布对比时,90米数据呈现出来的空间格局既有细节,又不至于碎得没法看,直接拿去出图完全没问题。
1.3 文件组织与数据格式的行内习惯
这类全国栅格产品,常见的格式是GeoTIFF,有的可能带压缩(比如LZW压缩),数据位深一般是32位浮点型,因为土壤厚度预测值不是整数,用整型存储会损失精度。文件组织上,有的按省分幅,有的是一张全国整图。这份数据从标题看是“全国覆盖”,那大概率是整幅发布,或者至少是按大区拼接好的。
拿到手先别急着用,第一时间用GIS软件看tif文件的元数据:行列数、投影、像元大小、NoData值、数据类型。这几项不搞清楚,后面做数据处理一定翻车。我在后面第3部分会详细说这一步该怎么检查。
2. 参数逐个拆解:90米、2010-2018、全国覆盖到底意味着什么
2.1 90米栅格的空间细节量到底有多少
很多人对分辨率“90米”没概念,我做个换算你就明白了。1°经纬度大约对应111公里,一个90米像元在经纬度坐标系里大约是0.0008°×0.0008°左右。放到实际地物上,90米大概能看出较大地块的边界、山体走向、流域轮廓;再小的地物比如田块内部差异、路边的带状土壤变化,基本是看不出来的。
所以在应用时,我建议把使用尺度定为:县域以上、中小流域以上。你如果要用它做某个村庄的地块评价,那就超出数据能力了。不是说不能用,而是那像元尺度已经大于你要评价的田块尺度了,结果没有意义。做全国土壤厚度分区、省级耕地质量背景分析、大流域侵蚀风险初筛,这才是它的主场。
2.2 时间标签要读懂:不是每年都更新
这个点我必须多说一嘴,因为太多人在这上面踩坑。标题里的“2010–2018年”,指的是这份产品的生产、整合和发布周期,而不是说土壤厚度在2010到2018年之间每一年都实测了一遍。土壤厚度这个属性,短时间内不会剧烈变化,没有哪套数据能逐年更新全国尺度的土壤厚度。
这个时间标签的真实含义,大致可以理解为:数据整合的剖面资料、辅助环境变量主要来自这个时间段,模型在这个时间窗口内完成训练和输出。换句话说,你想用这个数据做2010年到2018年之间的土壤厚度动态变化分析,是做不了的。但如果你要分析的空间格局、做现状评价、做模型背景参数,完全没问题。千万不要拿这个数据去讲“这些年土壤厚度变化了多少”,那属于误用。
2.3 栅格里的“土壤厚度”是怎么定义的
土壤厚度在专业语境里不是随便一个深度值。通常指的是土体厚度,或者叫有效土层厚度,也就是从地表向下到达基岩、母质层或其它障碍层(比如永冻层、硬磐层)的深度。这份栅格数据的值域一般以厘米为单位。拿到手之后,你先看一下全图统计值,正常情况下,平原区可能在100到200厘米之间,山区石质土壤可能只有20到50厘米,水体或者冰川区域通常被设为NoData。
这里有个容易忽略的问题:不同来源的“土壤厚度”定义有细微差异,有的数据用“根系限制深度”,有的用“土体厚度”,这两个概念在大陆性土壤和山地土壤上差别还挺大。使用前建议找一下配套的说明文档,看它到底是哪种定义。如果找不到说明,就从数值分布上判断——如果山区大量低值、平原大量高值,且中间过渡自然,一般是土体厚度;如果数值普遍偏深,可能测的是根系可及深度。
3. 数据落地实操:从裸数据到可用图层
3.1 第一步永远是检查元数据,别跳步
拿到tif后,不管多着急,先打开元数据看一遍。我用QGIS和Python都做过检查,两边的路径略有不同,但核心检查项是同一组:
- 坐标系:是WGS84经纬度,还是Albers等积投影,还是UTM分带?这直接决定你后面处理的空间参考框架。
- 像元大小:是不是规整的90×90米,还是以度为单位的约0.0008度。后者在跨纬度区域会导致实际面积扭曲。
- NoData值:常见的有-9999、-3.4028235e+38、0、255,不同产品设置不同,处理时要用真实NoData值来掩膜,不能用0一刀切。
- 数据类型:uint8、int16、float32都有可能,float32较常见,因为模型预测值带小数。
- 数据范围:国标值域一般在0到300厘米左右,如果看到负值或异常大值,多半是NoData处理或边缘效应问题。
用QGIS看的话,右键图层属性里就能看到大部分信息。用Python的话,一行rasterio就能搞定。
import rasterio with rasterio.open("soil_depth_90m.tif") as src: print(src.crs) # 坐标系 print(src.transform) # 仿射变换参数,能看出像元大小 print(src.width, src.height) # 行列数 print(src.nodata) # NoData值 print(src.dtypes) # 数据类型 # 快速看基本统计 from rasterio.plot import show_hist show_hist(src, bins=50)这一步不花几分钟,但能省掉后面一大堆排查时间。我第一次拿到类似数据时没查NoData值,直接按0处理,结果水体区域全部变成了“厚度为0的极端薄土”,画出来的图把自己吓一跳。
3.2 投影转换与重采样:对齐是分析的前提
如果你的研究区在某个省,而你手上的行政区划、气象站点、土地利用数据都是CGCS2000或者Albers投影,那这份栅格也必须统一到这个框架里。90米分辨率的数据在重采样时,我建议用双线性(bilinear)或三次卷积(cubic)方法,因为土壤厚度是连续变量,不是类别变量,最近邻法会丢掉渐变信息。
命令行里用gdalwarp很方便,QGIS里用栅格投影工具也一个效果:
gdalwarp -t_srs EPSG:3857 -tr 90 90 -r bilinear -dstnodata -9999 soil_depth_90m.tif soil_depth_3857.tif注意这里-tr 90 90的单位是米,前提是目标坐标系是投影坐标系。如果你要转到经纬度WGS84,那-tr的单位是度,不能直接用90,那是90度,等于把全国压成一个点。跨系统的朋友最容易在这个参数上翻车,我就见过有人把-tr 0.0008 0.0008写成-tr 90 90,结果栅格拉伸成一片色块。
3.3 裁剪到研究区:行政边界还是流域边界
做地方项目,大多数情况需要把全国数据裁剪到目标区域。裁剪有两种思路:按行政区边界,按自然边界(比如流域、生态功能区)。行政边界适合做政策评估、农业区划;流域边界适合做水文模型、土壤侵蚀评价。
用QGIS的话,直接在“提取-按掩膜提取”里选你的shp边界就行。用gdalwarp同样能完成:
gdalwarp -cutline study_area.shp -crop_to_cutline -dstnodata -9999 soil_depth_90m.tif soil_depth_study.tif这命令会自动依据矢量边界裁剪。我习惯在裁剪后再做一次统计,确认裁剪结果里有效像元的数量与边界面积预期相符。如果像元数量少了一大截,往往是边界坐标系和数据坐标系不一致,或者矢量边界存在拓扑问题,先统一坐标系再裁剪。
3.4 重分类与出图:让数据会说话
拿到连续的厚度栅格,如果要用于分区评价,通常要重分类成几个等级。国内土壤厚度分级有一套比较通用的习惯,我参考过耕地质量等级相关标准,大致可以按以下阈值划分:
| 厚度范围(cm) | 等级描述 | 典型区域举例 |
|---|---|---|
| 0–30 | 薄土层 | 石质山地、裸岩区 |
| 30–60 | 中薄层 | 丘陵坡地、半干旱区 |
| 60–100 | 中厚层 | 黄土高原塬区、部分山前平原 |
| 100–150 | 厚层 | 东北黑土区、华北平原 |
| >150 | 极厚层 | 冲积平原、部分盆地 |
在QGIS里可以用栅格计算器做重分类,也可以用Python的numpy一步到位:
import rasterio import numpy as np with rasterio.open("soil_depth_90m.tif") as src: data = src.read(1) profile = src.profile # 复制一份用于分类 classified = np.zeros_like(data, dtype=np.int8) classified[(data >= 0) & (data < 30)] = 1 classified[(data >= 30) & (data < 60)] = 2 classified[(data >= 60) & (data < 100)] = 3 classified[(data >= 100) & (data < 150)] = 4 classified[data >= 150] = 5 # 掩膜NoData classified[data == src.nodata] = -99 profile.update(dtype=np.int8, count=1, nodata=-99) with rasterio.open("soil_depth_class.tif", "w", **profile) as dst: dst.write(classified, 1)出图的时候,用渐变色调表示连续厚度,用离散配色表示等级,两种图表达的信息不一样。连续图适合展示空间趋势,分类图适合业务决策。我一般两个都出,汇报时用分类图,论文里放连续图。
4. 把数据用起来的典型场景:不只是画一张厚度图
4.1 区域土壤碳储量估算:三位一体计算
土壤厚度是碳储量估算的关键参数。无论用哪套公式,区域土壤有机碳储量大体上都是:有机碳库 = 土壤有机碳含量(SOC浓度)× 容重 × 土层厚度 × (1 – 砾石含量)。这里有三个变量,厚度就是其中一个乘法因子。
我在东北某流域做过一次估算:用实测的SOC含量和容重作为固定参数,分别用90米厚度数据和1公里厚度数据计算碳储量。结果1公里数据算出来的总储量比90米数据高出约12%。原因很直接——1公里栅格把很多薄土层山地区域抹平了,导致厚度被系统性高估。这种差异对区域碳收支评估影响非常大,你如果用粗分辨率数据做碳中和核算,误差可能会被放大到不可接受。
4.2 土壤侵蚀敏感性评估:厚度是“可蚀存量”的指示剂
在土壤侵蚀模型里,比如RUSLE系列,厚度不直接进入方程,但做侵蚀敏感性评价时,土层厚度决定了“还能被蚀掉多少”。我把90米厚度栅格跟坡度、降雨侵蚀力、植被覆盖因子叠加做敏感性分级,得到了一个很有意思的结果:同样是高坡度区域,基岩山区由于土层薄,侵蚀后恢复潜力低,生态脆弱等级明显高于土层厚的土石山区。这个判断只能靠厚度数据来区分,单看坡度数据是会误解的。
4.3 耕地质量与作物适宜性评价:厚度是硬指标
有效土层厚度是耕地质量评价、农用地分等的必查指标。很多省份的耕地质量等级标准里,土层厚度直接占权重,而且档位划分很细。用90米数据做县域耕地质量背景分析,比用统计数据或者经验赋值靠谱得多。把一个县的耕地地块边界叠加上来,统计每个地块内厚度的均值、最小值、变异系数,能很好地反映地力空间分布。这里要注意的是,地块尺度远小于90米时,单一像元可能覆盖多个地块,要用主导像元法或者面积加权法来提取,别直接用中心点取值。
4.4 水文模型和陆面过程模型的输入参数
SWAT、VEPO、DNDC这类模型通常需要土壤剖面参数,其中就包括土层厚度。90米分辨率对中小流域来说,正好可以代表HRU或网格单元的输入值。我试过把这份数据转成SWAT的土壤输入表,过程不算复杂:先按HRU边界做分区统计,再写出对应的参数表格。如果你的研究区在数据覆盖范围内,这一步比手动查土种志高效得多。
5. 真实使用中的坑与排查技巧
5.1 常见问题速查表
下面这些坑都是我在处理过程中真实遇到过的,整理成表方便大家对照排查:
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 全图一片色,拉伸不明显 | NoData值没被正确识别,导致极值污染统计范围 | 在样式设置里勾选“自定义NoData值”,用元数据里的真实值掩膜 |
| 投影后栅格变形严重 | -tr单位写错,投影坐标和经纬度坐标混用 | 检查gdalwarp参数,投影坐标系用米,地理坐标系用度 |
| 裁剪后边界出现黑边或白边 | 裁剪时没有设置输出NoData,或矢量与栅格坐标系不一致 | 添加-dstnodata,裁剪前统一用gdalwarp -t_srs重投影 |
| 提取点值时出现负值 | 数据里有负的NoData残留,或边缘外插值 | 提取前做一次条件掩膜,负值统一转NoData |
| 与同区域的30米数据对比差异大 | 数据源本身是预测结果,不同产品存在系统性偏差 | 用实测剖面点验证,评估偏差方向后再决定是否可用 |
| 栅格文件打开极慢 | 全国整幅tif过大,未做压缩或金字塔 | 转成Cloud Optimized GeoTIFF,或者在QGIS里先建金字塔 |
5.2 三个让数据更稳的小技巧
第一个技巧:先提点再建模型。无论做回归、随机森林还是深度学习,拿这份栅格做特征变量时,先在你自己的实测点位上提取厚度值,做一次简单的相关分析和偏差图。如果偏差有空间结构(比如东部偏高西部偏低),说明这数据在你研究区可能有系统性偏差,用的时候最好做一个回归校正。
第二个技巧:存成COG格式。全国90米栅格大概在几百MB到1GB级别,普通tif打开和做局部计算都慢。用rio cogeo或者GDAL转成COG后,按需读取会快非常多,而且Web上直接发布也方便。
gdal_translate soil_depth_90m.tif soil_depth_cog.tif -co TILED=YES -co COPY_SRC_OVERVIEWS=YES -co COMPRESS=LZW gdaladdo -r average soil_depth_cog.tif 2 4 8 16 32第三个技巧:同类数据交叉验证。土壤厚度不是唯一能反映土层深浅的数据,你可以拿地形湿度指数(TWI)、坡度、岩性图做交叉验证。正常情况下,陡坡和裸露基岩区的厚度应该低,冲积平原和高阶地厚度应该高。如果数据和这些常识冲突,那大概率是数据源问题,尽早排查,别等分析做完再回头看。
根据我个人经验,90米分辨率、全国覆盖的土壤厚度栅格,在当下国内公开数据里算得上“刚需级别”的优秀底图。它的合理性在于尺度选得聪明:比1公里精细得多,比30米少了很多噪声和覆盖缺失,能稳稳支撑起县域到国家尺度的研究与生产任务。四五年下来,我拿它做过碳储量估算、耕地质量背景分析、侵蚀风险分区、水文模型参数化,每一次都是作为主力底图使用。只要把NoData、投影和重采样这三个基础功夫做扎实,这份数据能给你省下的时间,远比你想象的要多。