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.y28362852),我发现 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 赋值运算符是&lt;-=

要获取有关它们的信息,请键入:

 ?`<-` 

而不是在你的命令行中&lt;-。还有一个操作符&lt;&lt;-影响父环境中的变量。

关于 := ,此运算符是 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 运算符 &lt;-= 和较小的扩展 &lt;&lt;- 混淆。 @RomainJacotin CRAN 是 R 本身的一个大型测试套件 - R 的这种更改会导致数百个包失败,直接依赖 + 更多间接依赖。 IMO R 中未使用的:= 运算符是一项功能,实际上可能会有更多这样的运算符。此外,R 不提供可以替代该 data.table 有价值的功能的功能,所以我不知道有什么理由可以证明您提到的场景是合理的。【参考方案3】:

(注意:这不是对原始问题的直接回答。由于我没有足够的声誉来发表评论,而且我认为下面的信息很有用,我还是把它作为答案。请告诉我如果有更好的方法!)

虽然您不能直接将:= 用作=&lt;-,但:= 运算符在使用非标准评估(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 代码。

您可以通过dplyrhere 阅读有关 NSE 和编程的更多信息。它很好地解释了在使用dplyr 函数编写自己的函数时如何处理 NSE。我上面的例子是直接从网站上复制过来的。

【讨论】:

我认为这是一个正确的答案,因为大多数人只会从 data.tabletidyverse 知道:=。我要补充一点,这些包实际上都没有执行它们的 := 定义中包含的代码,它们只是使用它,因为它具有方便和运算符优先级,并在兼容参数中使用时解析包含它的表达式。 问题:你必须从某个地方导入:= 吗?我正在构建一个包,其函数的语法与上面的my_mutate() 非常相似,R CMD CHECK 给了我no visible global function definition for ‘:=’ 错误。想法? 哦等等,我想我找到了答案:community.rstudio.com/t/undefined-global-functions-or-variables/… 短版:@importFrom rlang :=

以上是关于R 赋值运算符 := 有啥用?的主要内容,如果未能解决你的问题,请参考以下文章

在C语言中赋值运算符有啥作用?

C++中赋值运算操作符和=重载有啥区别?

javascript中的new有啥用

赋值运算符和复制构造函数有啥区别?

+=和=+ C赋值运算符有啥区别[重复]

在 C 中评估赋值运算符的左操作数有啥意义?