相同的代码(使用 R 的 dplyr、stringr 和 sf)在使用不同的包版本时会产生不同的结果

问题描述 投票:0回答:1

我尝试使用具有不同版本软件包的计算机运行相同的 R 代码,但在其中一个中代码可以工作,而在另一个中则产生错误。

具体来说,我从 this link 下载了文件,并将

stringr
str_remove
函数与
dplyr
rename_with
函数组合起来,以重命名
sf
类数据框中的变量(这样我就可以拥有变量根据我在其他文件中的名称标准化的名称)。我运行的代码如下:

library(tidyverse)
library(sf)
library(stringr)

dft <- st_read(file.path('D:', 'Downloads', 'tl_rd22_01_cd118.shp'), quiet = TRUE) %>% 
  rename_with(., .fn = str_remove, pattern = '\\d{2}$')

在其中一台计算机中,代码按预期运行(删除某些变量名称末尾的数字),但在另一台计算机中,它产生以下错误消息(翻译成英语时):

Error in .fn(names(agr)) : argument "pattern" missing, no pattern

但是,在显示错误的计算机中,以下代码可以工作。

library(tidyverse)
library(sf)
library(stringr)

dft <- st_read(file.path('D:', 'Downloads', 'tl_rd22_01_cd118.shp'), quiet = TRUE) %>% 
  st_drop_geometry(.) %>%
  rename_with(., .fn = str_remove, pattern = '\\d{2}$')

这个解决方案的问题是我失去了几何列。 这个错误消息对我来说似乎没有意义。问题似乎出在两台计算机上的版本上。在有效的版本中,

dplyr
stringr
sf
的版本分别是1.0.7、1.4.0和1.0.3;不起作用的版本是 1.1.4、1.5.1 和 1.0.14。对我来说,似乎
replace_with
sf
类的对象之间存在一些不兼容性。

r dplyr version stringr r-sf
1个回答
3
投票

sf
有一个新方法:
rename_with.sf
自版本1.0-13

sf:::rename_with.sf
#> function (.data, .fn, .cols, ...) 
#> {
#>     if (!requireNamespace("rlang", quietly = TRUE)) 
#>         stop("rlang required: install that first")
#>     .fn = rlang::as_function(.fn)
#>     agr = st_agr(.data)
#>     ret = NextMethod()
#>     names(agr) = .fn(names(agr))
#>     st_agr(ret) = agr
#>     ret
#> }
#> <bytecode: 0x00000235ee991c48>
#> <environment: namespace:sf>

这意味着在这种情况下,

...
不会传递给函数,就像
rename_with.data.frame
:

一样
dplyr:::rename_with.data.frame
#> function (.data, .fn, .cols = everything(), ...) 
#> {
#>     .fn <- as_function(.fn)
#>     cols <- tidyselect::eval_select(enquo(.cols), .data, allow_rename = FALSE)
#>     names <- names(.data)
#>     sel <- vec_slice(names, cols)
#>     new <- .fn(sel, ...)
#>     if (!is_character(new)) {
#>         cli::cli_abort("{.arg .fn} must return a character vector, not {.obj_type_friendly {new}}.")
#>     }
#>     if (length(new) != length(sel)) {
#>         cli::cli_abort("{.arg .fn} must return a vector of length {length(sel)}, not {length(new)}.")
#>     }
#>     names <- vec_assign(names, cols, new)
#>     names <- vec_as_names(names, repair = "check_unique")
#>     set_names(.data, names)
#> }
#> <bytecode: 0x00000235ee381aa0>
#> <environment: namespace:dplyr>

对于工作方法,您可以尝试使用

purrr
函数显式传递参数:

library(tidyverse)
library(sf)

download.file("https://www2.census.gov/geo/tiger/TIGER_RD18/LAYER/CD/tl_rd22_01_cd118.zip", "tl_rd22_01_cd118.zip")

unzip("tl_rd22_01_cd118.zip")

st_read('tl_rd22_01_cd118.shp', quiet = TRUE) |> 
  rename_with(~ str_remove(.x, pattern = '\\d{2}$')) 
#> Simple feature collection with 7 features and 12 fields
#> Geometry type: MULTIPOLYGON
#> Dimension:     XY
#> Bounding box:  xmin: -88.47323 ymin: 30.14442 xmax: -84.88825 ymax: 35.00803
#> Geodetic CRS:  NAD83
#>   STATEFP GEOID CD118FP                 NAMELSAD LSAD CDSESSN MTFCC FUNCSTAT
#> 1      01  0101      01 Congressional District 1   C2     118 G5200        N
#> 2      01  0102      02 Congressional District 2   C2     118 G5200        N
#> 3      01  0103      03 Congressional District 3   C2     118 G5200        N
#> 4      01  0104      04 Congressional District 4   C2     118 G5200        N
#> 5      01  0105      05 Congressional District 5   C2     118 G5200        N
#> 6      01  0106      06 Congressional District 6   C2     118 G5200        N
#> 7      01  0107      07 Congressional District 7   C2     118 G5200        N
...

或者在函数调用中显式使用

dplyr:::rename_with.data.frame
方法:

st_read('tl_rd22_01_cd118.shp', quiet = TRUE) %>%
  dplyr:::rename_with.data.frame(., .fn = str_remove, pattern = '\\d{2}$')

编辑 - 建议修复

我建议潜在的 GitHub 修复,因为我认为最简单的调整是将 this line 更改为:

names(agr) = .fn(names(agr))

至:

names(agr) = .fn(names(agr), ...)
© www.soinside.com 2019 - 2024. All rights reserved.