使用粘贴创建命名向量时出现问题

use*_*230 2 r vector

这似乎是一个基本问题,但我找不到对此的解释。

我可以这样命名一个向量:

values = c("lab1" = "my_lab1", 
           "lab2" = "my_lab2")
values
#      lab1      lab2 
# "my_lab1" "my_lab2" 
Run Code Online (Sandbox Code Playgroud)

我可以通过使用paste0创建元素来创建相同的向量,如下所示:

values = c("lab1" = "my_lab1", 
           "lab2" = paste0("my_lab", "2"))
values
#      lab1      lab2 
# "my_lab1" "my_lab2"
Run Code Online (Sandbox Code Playgroud)

但是当您尝试使用 创建名称时paste0,会导致错误:

values = c("lab1" = "my_lab1", 
           paste0("lab", "2") = "my_lab2")
# Error: unexpected '=' in:
# "values = c("lab1" = "my_lab1", 
#            paste0("lab", "2") ="
Run Code Online (Sandbox Code Playgroud)

为什么是这样?考虑到以下情况属实:

identical("lab2", paste0("lab", "2"))
[1] TRUE
Run Code Online (Sandbox Code Playgroud)

解决方案是使用setNames,但我对为什么上述问题很感兴趣:

setNames(c("my_lab1", "my_lab2"), c("lab1", paste0("lab", "2")))
#      lab1      lab2 
# "my_lab1" "my_lab2"
Run Code Online (Sandbox Code Playgroud)

我在Advanced Rvector部分看不到任何提及这一点。

谢谢

MrF*_*ick 6

问题在于命名参数根本不会被评估。它们被假定为文字值。考虑以下情况

foo <- function(a=5, x=10) {a+x}
Run Code Online (Sandbox Code Playgroud)

然后你做到了

x <- "a"
foo(x = 2)
foo(paste(x) = 2) # error
Run Code Online (Sandbox Code Playgroud)

如果您期望对“x”进行求值,则实际应该运行的内容可能会变得非常混乱。R 解析器不希望将表达式视为参数名称。语法在 R 源代码中定义。R 语言定义中也引用了这一事实,其中指出

每个参数都可以被标记(tag=expr),或者只是一个简单的表达式。它也可以为空,也可以是特殊标记之一...、..2 等。 [...] 标记可以是标识符或文本字符串。

这确实意味着标签本身不能是表达式。

在示例中我用作foo函数,但c也只是一个函数。虽然它没有显式命名参数,但它确实遵循其他函数有关参数名称的所有相同规则。

在 tidyverse/rlang 世界中,他们定义了一个新函数:=,允许您使用参数名称

rlang::list2("lab1" = "my_lab1", 
               !!paste0("lab", "2") := "my_lab2")
# $lab1
# [1] "my_lab1"
# $lab2
# [1] "my_lab2"
Run Code Online (Sandbox Code Playgroud)

但为了做到这一点,不可能使用=,他们必须使用:=R 中的函数,而不是特殊字符,并且他们在执行时手动重写调用。

  • 一个很好的添加参考可能是 R 语言定义中的[表达式/函数调用](https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Function-calls-_0028expressions_0029) 。它指定函数参数可以“标记”为“tag = expr”,并且标记可以是“标识符或文本字符串”,但(通过省略暗示)不是表达式。 (2认同)