R 赋值运算符 := 有啥用?
Posted
技术标签:
【中文标题】R 赋值运算符 := 有啥用?【英文标题】:What is the R assignment operator := for?R 赋值运算符 := 有什么用? 【发布时间】:2015-12-25 09:18:06 【问题描述】:通过深入研究 R 源代码(文件 R-3.2.2/src/main/gram.y
行 2836
到 2852)
,我发现 R 解析器/标记器认为 :=
是 LEFT_ASSIGNMENT
标记。
但是当尝试在R.3.2.2
中将其用作赋值运算符时,
我有一个错误(无法找到 :=
的函数 ...),但正如您所见,R 将其视为像 <-
这样的赋值:
> myVar := 42
Erreur : impossible de trouver la fonction ":="
> :=
Erreur : unexpected assignment in ":="
> <-
Erreur : unexpected assignment in "<-"
这是一个错误,还是需要从标记器源代码中删除标记 :=
?
有没有关于 R 中 :=
运算符的过去故事?
【问题讨论】:
:=
在data.table
中是一个非常方便的运算符,但据我所知,在 R 中还不是(还没有?)
不相关-为什么一半的R错误输出是英文?我假设您将语言环境设置为法语。
相关:***.com/questions/7033106***.com/questions/26269423
【参考方案1】:
这是以前允许的赋值运算符,请参阅 John Chambers 在 2001 年的 this article。
R 的开发版本现在允许编写一些赋值 C 或 Java 风格,使用 = 运算符。这增加了兼容性 使用 S-Plus(以及使用 C、Java 和许多其他语言)。
所有以前允许的赋值运算符(
:=
功能似乎不再存在,但您可以像这样“重新启用它”:
`:=` <- `<-`
x:=3
x
[1] 3
【讨论】:
James,仅供参考,目前似乎 '_' 不被视为 R-3.2.2 解析器/标记器的分配(只需在提示符上单独输入,您将获得“意外输入”而不是“意外分配”,因为您只需键入 ' @RomainJacotin 是的,下划线在 1.8.0 版中已作为赋值运算符被删除,但我在新闻文件中没有发现任何关于:=
的提及。 svn.r-project.org/R/trunk/doc/NEWS.1
我认为他们只是忘记删除它,然后马特带来了 data.table,现在他们不能再删除它了。【参考方案2】:
为了澄清,R
赋值运算符是<-
和=
。
要获取有关它们的信息,请键入:
?`<-`
而不是在你的命令行中<-
。还有一个操作符<<-
影响父环境中的变量。
关于 :=
,此运算符是 data.table
包中的 j
运算符。它可以读取 defined as
并且只能在 data.table
对象中使用。为了说明这一点,当第一列中的值等于1
时,我们将第二列修改为b
(将col2
定义为b
):
library(data.table)
dt <- data.table(col1=c(1,2,1,2,3), col2 = letters[1:5])
dt[col1==1, col2:='b']
详细解释:
?`:=`
希望它澄清。
【讨论】:
我猜解析器代码中的那些行就是为什么可以定义:=
。我记得读过类似的东西,但忘了在哪里。也许马特或阿伦可以澄清一下。
实际上 data.table 包定义了一个自定义的 ':=' 函数,该函数利用了在 R 解析器/标记器中定义的 ':=' 赋值运算符,但它没有被非正式地描述/写在任何地方在 R 语言中......下一个问题:对于每个人(以及 data.table 维护者......)来说,使用这个 ':=' 令牌真的安全且面向未来吗? data.table 开发人员是否要求 R 核心团队添加此 ':=' 分配令牌?
@RomainJacotin R-core 极不可能以破坏广泛使用的 data.table 包的方式更改解析器。他们非常注意向后兼容性。
这样定义这个运算符很有用,因为它通过reference
来修改data.table
对象。不会与传统的基本 R 运算符 <-
、=
和较小的扩展 <<-
混淆。
@RomainJacotin CRAN 是 R 本身的一个大型测试套件 - R 的这种更改会导致数百个包失败,直接依赖 + 更多间接依赖。 IMO R 中未使用的:=
运算符是一项功能,实际上可能会有更多这样的运算符。此外,R 不提供可以替代该 data.table 有价值的功能的功能,所以我不知道有什么理由可以证明您提到的场景是合理的。【参考方案3】:
(注意:这不是对原始问题的直接回答。由于我没有足够的声誉来发表评论,而且我认为下面的信息很有用,我还是把它作为答案。请告诉我如果有更好的方法!)
虽然您不能直接将:=
用作=
或<-
,但:=
运算符在使用非标准评估(NSE) 的领域特定语言(DSL) 进行编程时非常有用,例如@ 987654327@ 和data.table
。下面是一个例子:
library(dplyr)
df <- tibble(
g1 = c(1, 1, 2, 2, 2),
g2 = c(1, 2, 1, 2, 1),
a = sample(5),
b = sample(5)
)
my_mutate <- function(df, expr)
expr <- enquo(expr)
mean_name <- paste0("mean_", quo_name(expr))
sum_name <- paste0("sum_", quo_name(expr))
mutate(df,
!! mean_name := mean(!! expr),
!! sum_name := sum(!! expr)
)
my_mutate(df, a)
#> # A tibble: 5 x 6
#> g1 g2 a b mean_a sum_a
#> <dbl> <dbl> <int> <int> <dbl> <int>
#> 1 1. 1. 1 3 3. 15
#> 2 1. 2. 4 2 3. 15
#> 3 2. 1. 2 1 3. 15
#> 4 2. 2. 5 4 3. 15
#> # ... with 1 more row
在上面的示例中,将my_mutate
函数中的:=
替换为=
将不起作用,因为!! mean_name = mean(!! expr)
不是有效的R 代码。
您可以通过dplyr
here 阅读有关 NSE 和编程的更多信息。它很好地解释了在使用dplyr
函数编写自己的函数时如何处理 NSE。我上面的例子是直接从网站上复制过来的。
【讨论】:
我认为这是一个正确的答案,因为大多数人只会从data.table
和 tidyverse
知道:=
。我要补充一点,这些包实际上都没有执行它们的 :=
定义中包含的代码,它们只是使用它,因为它具有方便和运算符优先级,并在兼容参数中使用时解析包含它的表达式。
问题:你必须从某个地方导入:=
吗?我正在构建一个包,其函数的语法与上面的my_mutate()
非常相似,R CMD CHECK
给了我no visible global function definition for ‘:=’
错误。想法?
哦等等,我想我找到了答案:community.rstudio.com/t/undefined-global-functions-or-variables/… 短版:@importFrom rlang :=
以上是关于R 赋值运算符 := 有啥用?的主要内容,如果未能解决你的问题,请参考以下文章