我不明白为什么下面代码块中的最后两个示例失败了

library(sf)
#> Linking to GEOS 3.11.2, GDAL 3.7.2, PROJ 9.3.0; sf_use_s2() is TRUE

p1 <- st_sfc(st_point(c(0, 0)))
p2 <- st_sfc(st_point(c(1, 1)))

p1[p2]
#> Geometry set for 0 features 
#> Bounding box:  xmin: NA ymin: NA xmax: NA ymax: NA
#> CRS:           NA
p1[p2, op = st_intersects]
#> Error in `[.default`(p1, p2, op = st_intersects): incorrect number of dimensions
p1[p2, , op = st_intersects]
#> Error in `[.default`(p1, p2, , op = st_intersects): incorrect number of dimensions

[.sfc指定的默认操作恰好是st_intersects时.

sf:::`[.sfc`
#> function (x, i, j, ..., op = st_intersects) 
#> {
#>     if (!missing(i) && (inherits(i, "sf") || inherits(i, "sfc") || 
#>         inherits(i, "sfg"))) 
#>         i = lengths(op(x, i, ...)) != 0
#>     st_sfc(NextMethod(), crs = st_crs(x), precision = st_precision(x), 
#>         dim = if (length(x)) 
#>             class(x[[1]])[1]
#>         else "XY")
#> }
#> <bytecode: 0x00000255ad682df8>
#> <environment: namespace:sf>

创建于2024-01-21,包含reprex v2.0.2

你能帮帮我吗?对子设置sfc对象时,我应该如何正确地指定op参数?

推荐答案

这里出现问题是因为`[.sfc`在内部使用NextMethod().其工作方式是将显式传递给`[.sfc`的参数传递给列表的默认子设置方法.这是在C代码函数do_subset_dflt中实现的原语"["函数.

对于R函数来说,这是不寻常的,它忽略所有参数的名称(除了drop以外),并且只按顺序执行:

my_list <- list(a = 1, b = 2)

my_list[the_name_of_this_argument_is_ignored = 2]
#> $b
#> [1] 2

my_list[the_name_of_this_argument_is_ignored = 2, drop = FALSE]
#> $b
#> [1] 2

这甚至导致了令人困惑的结果

my_mat <- matrix(1:4, 2, 2)

my_mat[i = 1, j = 2]
#> [1] 3

my_mat[j = 1, i = 2]
#> [1] 3

如果(非删除)参数的数量超过了对象的维度数量,我们就会得到您的错误:

my_list[2, op = sf::st_intersects]
#> Error in my_list[2, op = sf::st_intersects] : 
#>   incorrect number of dimensions

默认参数可以毫无问题地工作,这似乎令人困惑,但进行完全相同的函数调用但显式命名默认参数会引发错误.这是NextMethod工作方式的结果-它只传递您专门传递给初始调用的符号,而忽略任何默认参数.

通过创建一个具有自己的子集方法的新类,可以非常容易地显示整个情况:

test <- function(x) structure(matrix(x, 2, 2), class = "test")

`[.test` <- function(x, i, j, ..., nag = FALSE) {
  if(nag) cat("This won't work now\n")
  NextMethod()
}

x <- test(5)

x[1, 1]
#> [1] 5

x[1, 1, nag = TRUE]
#> This won't work now
#> Error in `[.default`(x, 1, 1, nag = TRUE): incorrect number of dimensions

x[1, 1, nag = FALSE]
#> Error in `[.default`(x, 1, 1, nag = FALSE): incorrect number of dimensions

没有任何直接的解决办法,因为[是一个原始函数.NextMethod的使用意味着命名自变量op实际上不可供终端用户使用.由于该函数没有导出并且没有文档记录,因此这并不是一个真正的错误,但将op作为参数传递而不是在函数体中硬编码`st_intersects似乎是一个奇怪的设计决定.

与此同时,最好避免使用op参数,而直接使用谓词函数:

library(sf)
#> Linking to GEOS 3.9.3, GDAL 3.5.2, PROJ 8.2.1; sf_use_s2() is TRUE

p1 <- st_sfc(st_point(c(0, 0)))
p2 <- st_sfc(st_point(c(1, 1)))

p1[lengths(st_intersects(p1, p2)) != 0]
#> Geometry set for 0 features 
#> Bounding box:  xmin: NA ymin: NA xmax: NA ymax: NA
#> CRS:           NA

创建于2024-01-21,包含reprex v2.0.2

R相关问答推荐

为什么st_join(ob1,ob2,left = True)返回具有比ob1更多功能的sf对象?

r—绘制相交曲线

筛选出以特定顺序患病的个体

如何在一次运行中使用count进行多列计数

在df中保留原始变量和新变量

仅在Facet_WRAP()中的相应方面包含geom_abline()

按多列统计频次

R如何计算现有行的总和以添加新的数据行

停止ggplot将多行减少到一行

在R中使用列表(作为tibble列)进行向量化?

如何阻止围堵地理密度图?

为R中的16组参数生成10000个样本的有效方法是什么?

如何构建一个for循环来循环处理动物ID?

网络抓取新闻标题和时间

如何在shiny 的应用程序 map 视图宣传单中可视化单点

对一个数据帧中另一个数据帧中的值进行计数

将每晚的平均值与每晚的值进行比较,统计是否有效?

reshape 数据帧-基于组将行转换为列

使用dplyr删除具有条件的行

当y为负值时,无法使stat_cor正确定位到底部?