我尝试使用具有不同版本软件包的计算机运行相同的 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
类的对象之间存在一些不兼容性。
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), ...)