使用QGIS表达式验证降雨量数据的空间同质性

降雨量是最常见的水文气象变量,是许多水文应用(例如径流计算、洪水预报以及结构工程设计)不可或缺的基础数据。但是,由于系统误差或者人为因素,原始的降雨数据常常包含许多误差和不一致性,因此在使用降雨量数据进行分析前,必须对其可靠性进行严格验证。

在2020年11月27日QGIS开放日直播视频中,Ujaval Gandhi演示了使用QGIS表达式,通过与邻近站点进行比较来识别可疑降雨量观测值的空间方法验证降雨数据空间同质性,所讲解的方法和解决问题的思路使我收获颇丰,特整理出来与大家分享。

 01 降雨量观测数据检测

  • 降雨数据的空间相关性

降雨表现出一定程度的空间一致性。降雨测量的空间相关性取决于以下因素:

  • 持续时间(较短持续时间的相关性较小);

  • 距离(与距离增加的相关性较小);

  • 降水类型(对流降水的相关性较小);

  • 地形(与丘陵地形的相关性较小)。

  • 最近邻算法

假设降雨数据在较长的时间内进行汇总后,在较短距离内显示出一定的空间相关性。因此,可以对检测站点的降雨量测量值与相邻站点测量值做同质性验证,这是最近邻算法验证降雨量数据的基础,具体描述如下:

根据周围站点观测到的降雨量加权平均值,计算得出待检测站点降雨量的估算。如果观测值和估计值之间的误差超过预设的阈值,则认为该待检测站点的观测值可疑,将其标记以进一步调查其误差产生的可能原因。

——印度NHP降雨数据验证手册

  • QGIS实现最近邻算法

在QGIS中,最近邻算法可按以下步骤进行:

  • 识别邻近站点;

  • 计算待检测站点到邻近站点的距离;

  • 根据降雨量估算值标识可疑观察站点;

 02 操作步骤

  • 获取示范数据

本文中使用2020年6月佛罗里达州的降水数据为示范,来自全球历史气候学网络(GHCN)。

示范数据的下载地址:

链接:https://pan.baidu.com/s/1ufEwdqtmK0vMz9G1EFbZ-g

提取码:of8q

  • 识别和选择邻近观测站

选择邻近观测站必须满足以下条件:

  • 待测站点与相邻站点之间的距离必须小于指定的最大相关距离,例如Rmax为10(km);

  • 最多考虑8个邻近观测站;

  • 为了减少选择中的空间偏差,以待测试站的为中心,每个象限内最多选择两个邻近观测站点。

在示范数据中,点图层ghcn_stations包含佛罗里达州降雨量观测站的位置,使用aggregate()函数,查找10km(Rmax)范围内的相邻8个站点。

具体操作如下:图层面板中选中ghcn_stations,点击工具栏的【字段计算器】按钮,新建字符型字段“neighbors”,输入表达式:

array_to_string(array_slice(array_remove_all(aggregate(layer:= 'ghcn_stations',aggregate:='array_agg',expression:="NAME",filter:=distance($geometry, geometry(@parent)) < 10000,order_by:=distance($geometry, geometry(@parent))), "NAME"), 0, 7))

上面表达式将查找距离待检测站点10公里以内最多8个邻近站点。

为了保证每个象限最多选择2个站点,在属性表中增加4个新字段:Q1、Q2、Q3、Q4,分别存储第一、第二、第三和第四象限站点名称,使用字段计算器更新,其计算表达式如下:

Q1

array_to_string(array_slice(array_remove_all(aggregate(layer:= 'ghcn_stations',aggregate:='array_agg',expression:="NAME",concatenator:=',',filter:=distance($geometry, geometry(@parent)) < 10000 andangle_at_vertex(make_line(geometry(@parent), $geometry), 0) >=0 andangle_at_vertex(make_line(geometry(@parent), $geometry), 0) < 90,order_by:=distance($geometry, geometry(@parent))), "NAME"), 0, 1))

用相同方法依次更新Q2、Q3、Q4,其对应的表达式如下:

Q2

array_to_string(array_slice(array_remove_all(aggregate(layer:= 'ghcn_stations',aggregate:='array_agg',expression:="NAME",concatenator:=',',filter:=distance($geometry, geometry(@parent)) < 10000 andangle_at_vertex(make_line(geometry(@parent), $geometry), 0) >=270 andangle_at_vertex(make_line(geometry(@parent), $geometry), 0) < 360,order_by:=distance($geometry, geometry(@parent))), "NAME"), 0, 1))

Q3

array_to_string(array_slice(array_remove_all(aggregate(layer:= 'ghcn_stations',aggregate:='array_agg',expression:="NAME",concatenator:=',',filter:=distance($geometry, geometry(@parent)) < 10000 andangle_at_vertex(make_line(geometry(@parent), $geometry), 0) >=180 andangle_at_vertex(make_line(geometry(@parent), $geometry), 0) < 270,order_by:=distance($geometry, geometry(@parent))), "NAME"), 0, 1))

Q4

array_to_string(array_slice(array_remove_all(aggregate(layer:= 'ghcn_stations',aggregate:='array_agg',expression:="NAME",concatenator:=',',filter:=distance($geometry, geometry(@parent)) < 10000 andangle_at_vertex(make_line(geometry(@parent), $geometry), 0) >=90 andangle_at_vertex(make_line(geometry(@parent), $geometry), 0) < 180,order_by:=distance($geometry, geometry(@parent))), "NAME"), 0, 1))

验证一下四个象限数据的计算结果:

使用字段计算器输入下列表达式将四个象限的字段合并,得到最终的邻近站点名称字符串,更新到“neighbors”字段,并将结果保存到图层stations_with_neighbors中。

neighbors

array_to_string(array_remove_all(array_cat(coalesce(string_to_array(Q1), array()),coalesce(string_to_array(Q2), array()),coalesce(string_to_array(Q3), array()),coalesce(string_to_array(Q4), array())), "NAME"))

其中,coalesce() 函数确保在任何象限具有空(NULL)值的情况下表达式能返回正确的结果。

  • 计算待测站点与相邻站点的距离

要进行空间均质性检测,需要计算待测站点到每个邻近站点的距离,属性表中新建“distances”字段,使用字段计算器输入表达式如下:

distances

 array_to_string(array_foreach(string_to_array("neighbors"), round(distance($geometry, geometry(get_feature('stations_with_neighbors', 'NAME', @element)))/1000, 2)))

上面表达式中,array_foreach()函数遍历neighbors字段中每个相邻站点,计算其与待测站点之间的距离,并将计算结果转换为公里为单位,保存到字段“distances”中,将计算距离后的图层保存为station_with_distances。至此,我们得到了进行降雨量观测数据空间均质性分析所需的数据。

  • 使用QGIS识别可疑观测数据

使用QGIS识别可疑观测数据,需要动态构建统计表达式,并用eval()函数对表达式求值。

首先,打开字段计算器,新增整型“N”字段用于保存邻近点的数量,使用array_length函数求出邻近站点数量:

N

array_length(string_to_array( "neighbors" ))

接下来,使用邻近站点的降雨量观测值,结合它们到待检测站点的距离计算反距离加权平均值,得到估计的降水量Pest,表达式如下:

Pest

eval(array_to_string(array_foreach(string_to_array("neighbors"),(1/(distance($geometry,geometry(get_feature('station_with_distances', 'NAME', @element)))/1000)^2)*attributes(get_feature('station_with_distances', 'NAME', @element))['PRCP']),'+'))/eval(array_to_string(array_foreach(string_to_array("neighbors"),(1/(distance($geometry,geometry(get_feature('station_with_distances', 'NAME', @element)))/1000)^2)),'+'))

上述表达式创建一个由+字符分隔的字符串,并将其传递给eval(),eval()函数接收字符串,并以表达式执行该字符串,返回计算结果。

用同样方法,计算邻近站点降雨量观测值的均值mean和标准差standard deviation,表达式如下:

mean

eval(array_to_string(array_foreach( string_to_array( "neighbors" ), attributes(get_feature('station_with_distances', 'NAME', @element))['PRCP']), '+')) / "N"

stddev

sqrt(eval(array_to_string(array_foreach( string_to_array( "neighbors" ), (attributes(get_feature('station_with_distances', 'NAME', @element))['PRCP'] - "mean" )^2), '+')) / "N" )

我们需要的最终变量是absolute difference,即观测值和估计值之间的差:

absdiff

abs("PRCP" - "Pest")

确认降雨量观测数据正常的条件是:

  • 观测值与估计值之间的差小于等于75且观测值与估计值之间的差小于等于2个标准差;

  • 或者相邻站点的数量小于2;

  • 或者观测值与估计值之间的差计算结果为空值(NULL)。

运行空间均质性检测并标记降雨观测数据可疑站点:

suspect

CASE WHEN      ("absdiff" <= 75 and "absdiff" <= 2* "stddev")  or "N" <= 2 or "absdiff" is NULLTHEN  'No'  ELSE  'Yes' END

 03 验证结果

如下图,经过计算,站点ORLANDO 6.8 W反距离加权估计值是170.4,而实测值为98.3,差异过大,被标识为可疑数据,需要具体查找数据异常的原因。

版权声明

本文欢迎转载,转载时请注明出处。

猜你喜欢

转载自blog.csdn.net/QGISClass/article/details/110748671