R中raster::extract函数未按预期工作的问题与需求实现
raster::extract返回的单元数量不符合预期 你的第一个问题核心原因是**raster::extract默认只提取单元中心落在多边形内的栅格单元**,而不是所有与多边形相交的单元。这就导致那些仅部分被多边形覆盖、但中心不在多边形内的单元没有被统计进去,所以返回的数量比实际相交的少。
另外,你的代码里有个小错误:download.file的第二个参数是保存的文件名,你写的是'downloaded_raster',但后续加载用的是raster('test.tif'),这会导致加载失败(除非你手动重命名了文件),应该修正为:
download.file('https://raw.githubusercontent.com/JimShady/london_osm_canyons/master/test.tif', 'test.tif')
要正确统计所有与多边形相交的栅格单元数量(包含NA),需要使用weights=TRUE参数,这样extract会返回每个相交单元的覆盖权重(即使权重很小,只要>0就说明单元与多边形相交)。然后我们可以通过统计权重向量的长度来得到相交单元总数:
# 提取每个多边形的栅格值和对应权重 extract_result <- extract(raster, polygons, weights=TRUE, na.rm=FALSE) # 统计每个多边形的相交单元数(包括NA) polygons$cell_count <- sapply(extract_result, function(x) nrow(x))
这里extract_result是一个列表,每个元素是一个数据框,包含value(栅格值)和weight(覆盖权重)列,nrow(x)就是该多边形相交的单元总数。
你当前的加权均值代码有问题:当weights=TRUE时,extract会将权重传递给自定义函数,但mean函数不会自动使用这些权重。要实现只要相交单元存在NA就返回NA的加权均值,需要自定义函数调用weighted.mean并设置na.rm=FALSE:
polygons$mean <- round(extract(raster, polygons, weights=TRUE, na.rm=FALSE, fun=function(x, w) weighted.mean(x, w, na.rm=FALSE)), 2)
这样如果任何相交单元的值是NA,weighted.mean就会返回NA,符合你的要求。
同样利用weights=TRUE提取所有相交单元,然后自定义函数统计满足value < 1的单元个数,同时保留NA的影响(即只要有NA就返回NA):
polygons$almost_zero <- extract(raster, polygons, weights=TRUE, na.rm=FALSE, fun=function(x, w) sum(x$value < 1, na.rm=FALSE))
这里x是包含value列的数据框,sum(x$value < 1, na.rm=FALSE)会统计值小于1的单元数,如果存在NA,结果会是NA(因为na.rm=FALSE)。
- 如果你确实只需要单元中心在多边形内的单元数量,那原来的
fun=length是对的,但显然这不是你的需求。 - 当使用
weights=TRUE时,extract的计算量会稍大,因为需要计算每个单元与多边形的交集比例,但这是获取所有相交单元的必要步骤。
内容的提问来源于stack exchange,提问作者TheRealJimShady

