当前位置:  开发笔记 > 编程语言 > 正文

R中"="和"< - "之间有什么区别?

如何解决《R中"="和"<-"之间有什么区别?》经验,为你挑选了7个好方法。

赋值运算符=<-R 之间有什么区别?

我知道运营商略有不同,如本例所示

x <- y <- 5
x = y = 5
x = y <- 5
x <- y = 5
# Error in (x <- y) = 5 : could not find function "<-<-"

但这是唯一的区别吗?



1> Richie Cotto..:

当您使用它们在函数调用中设置参数值时,赋值运算符的差异会更明显.例如:

median(x = 1:10)
x   
## Error: object 'x' not found

在这种情况下,x声明在函数的范围内,因此它不存在于用户工作空间中.

median(x <- 1:10)
x    
## [1]  1  2  3  4  5  6  7  8  9 10

在这种情况下,x在用户工作区中声明,因此您可以在函数调用完成后使用它.


R社区普遍倾向于使用<-赋值(功能签名除外)与(非常)旧版本的S-Plus兼容.请注意,空格有助于澄清类似的情况

x<-3
# Does this mean assignment?
x <- 3
# Or less than?
x < -3

大多数R IDE都有键盘快捷键,<-以便于输入. Ctrl+ =在Architect中,Alt+ -在RStudio(Option+ -在macOS下),Shift+ -(下划线)在emacs + ESS中.


如果你喜欢写=<-,但要使用公开发布的代码比较常见的赋值符号(CRAN上,例如),那么你可以使用的一个tidy_*功能,在formatR包自动替换=<-.

library(formatR)
tidy_source(text = "x=1:5", arrow = TRUE)
## x <- 1:5

"为什么会x <- y = 5抛出错误而不是错误x <- y <- 5?" 这个问题的答案.是"这取决于解析器中包含的魔力".R的语法包含许多含糊不清的案例,必须以某种方式解决.解析器选择取决于是否解决以不同的顺序的表达的比特=<-使用.

要了解发生的情况,您需要知道该任务以静默方式返回已分配的值.例如,您可以通过显式打印更清楚地看到print(x <- 2 + 3).

其次,如果我们使用前缀表示法进行赋值,则更清楚.所以

x <- 5
`<-`(x, 5)  #same thing

y = 5
`=`(y, 5)   #also the same thing

解析器解释x <- y <- 5

`<-`(x, `<-`(y, 5))

我们可以预期,x <- y = 5那么将是

`<-`(x, `=`(y, 5))

但实际上它被解释为

`=`(`<-`(x, y), 5)

这是因为=优先级低于帮助页面<-上显示的优先级?Syntax.


我刚刚意识到你对`x < - x = 5`如何解释的解释有点错误:实际上,R把它解释为```< - < - `(x,y = 5,value = 5)` `(它本身或多或少等同于``tmp < - x; x < - `< - < - `(tmp,y = 5,value = 5)``).哎呀!
这一点也在Patrick Burns的[The R Inferno](http://www.burns-stat.com/pages/Tutor/R_inferno.pdf)第8.2.26章中提到过(不是我,而是建议)
但是,`median((x = 1:10))`与`median(x < - 1:10)`具有相同的效果.
…而且我刚刚意识到,这个答案的第一部分是错误的,并且很不幸,这是很容易引起误解的,因为它会造成一个普遍的误解:在函数调用中使用`=`的方式**不执行赋值**,并且不是赋值运算符。这是一个完全不同的已解析R表达式,恰好使用相同的字符。此外,您显示的代码不会在函数范围内“声明” x。功能声明执行所述声明。函数调用没有(使用命名的`...`参数会更复杂)。
我真的不考虑它们的快捷方式,无论如何您按相同数量的键
@DryLabRebel该快捷方式的问题是,R的最受推荐的样式约定在定界符“ like_this”中使用下划线,并且使用此快捷方式键入非常令人讨厌。

2> Nosredna..:

谷歌的R风格指南通过禁止分配"="来简化问题.不错的选择.

https://google.github.io/styleguide/Rguide.xml

R手册详细介绍了所有5个赋值运算符.

http://stat.ethz.ch/R-manual/R-patched/library/base/html/assignOps.html


当'x <-y`意味着"x <-y"意外分配的缺点时,我非常烦恼,我个人更喜欢`=`.让你的代码依赖于存在的空白对我来说似乎并不好.可以建议间距作为样式建议,但是无论空间是否存在,您的代码都会以不同的方式运行?如果您重新格式化代码,或使用搜索和替换,空格有时会消失,代码出错.这不是`=`的问题.IIUC,禁止`=`等同于要求"`< - `"; 即3个字符,包括空格,而不仅仅是"< - ".
如果可以使用`=`,为什么用`<-`伤害你的眼睛和手指?在99.99%的时间里`=`很好.有时候你需要`<< - `,这是一个不同的历史.
请注意,任何非0都被R视为"TRUE".因此,如果您打算测试`x`是否小于`-y`,您可能会编写`if(x <-y)`,它不会发出警告或错误,似乎工作正常.但是,当`y = 0`时,它只会是'FALSE'.
对< - 的关注可能是缺少+ =和 - =的蹩脚原因之一.
如果你禁止`=`并使用`< - `那么很难说不需要额外的'grep"[^ <] < - [^]"*.R`步骤.`=`不需要这样的`grep`.

3> Konrad Rudol..:

赋值运算符=<-R 之间有什么区别?

如您的示例所示,=并且<-具有稍微不同的运算符优先级(这决定了它们在同一表达式中混合时的评估顺序).实际上,?Syntax在R中给出了以下运算符优先级表,从最高到最低:

…
‘-> ->>’           rightwards assignment
‘<- <<-’           assignment (right to left)
‘=’                assignment (right to left)
…

但这是唯一的区别吗?

既然你在询问赋值运算符:是的,这是唯一的区别.但是,如果不相信你会被原谅.即使R文件?assignOps声称存在更多差异:

运算符<-可以在任何地方使用,而运算符=只允许在顶层(例如,在命令提示符下键入的完整表达式中)或作为支撑表达式列表中的子表达式之一.

我们不要过分夸大它:R文档(巧妙地)错误 [ 1 ].这很容易显示:我们只需要找到一个=运算符的反例,它不是(a)在顶层,也不是(b)在表达式(即{…; …})的支撑列表中的子表达式.- 无需再费周折:

x
# Error: object 'x' not found
sum((x = 1), 2)
# [1] 3
x
# [1] 1

显然,我们在=上下文(a)和(b)之外执行了一项任务.那么,为什么几十年来核心R语言功能的文档出错呢?

这是因为在R的语法中,符号=有两个不同的含义,这些含义经常混淆:

    第一个含义是作为赋值运算符.这是我们到目前为止所讨论的全部内容.

    第二个含义不是运算符,而是一个语法标记,表示在函数调用中传递的命名参数.与=运算符不同,它在运行时不执行任何操作,它只是更改表达式的解析方式.

让我们来看看.

在一般形式的任何代码中......

‹function_name›(‹argname› = ‹value›, …)
‹function_name›(‹args›, ‹argname› = ‹value›, …)

... =是定义命名参数传递的标记:它不是赋值运算符.此外,在某些句法语境中=完全被禁止:

if (‹var› = ‹value›) …
while (‹var› = ‹value›) …
for (‹var› = ‹value› in ‹value2›) …
for (‹var1› in ‹var2› = ‹value›) …

其中任何一个都会在中引发错误"unexpected'='.

在任何其他上下文中,=指赋值运算符调用.特别是,仅在子表达式周围加上括号使得上述(a)中的任何一个有效,(b)赋值.例如,以下执行赋值:

median((x = 1 : 10))

但是也:

if (! (nf = length(from))) return()

现在你可能会反对这样的代码是残暴的(你可能是对的).但是我从base::file.copy函数中取代了这个代码(替换<-=) - 它在核心R代码库的大部分内容中都是普遍存在的模式.

John Chambers的原始解释,R文档可能基于此,实际上解释了这一点:

[ =赋值]只允许在语法中的两个位置:在顶层(作为完整的程序或用户类型的表达式); 当与周围的逻辑结构隔离时,通过括号或一对额外的括号.


坦白:我早先撒了谎.还有在之间的一个额外的差异=<-经营者:他们调用不同的功能.默认情况下,这些函数执行相同的操作,但您可以单独覆盖它们中的任何一个以更改行为.相比之下,<-->(左到右分配),虽然语法不同,总是调用相同的功能.覆盖一个也会覆盖另一个.知道这一点很少实用,但它可以用于一些有趣的恶作剧.


(

(
,

, …)



in
in

) …

4> Steve Pitche..:

x = y = 5相当于x = (y = 5),因为赋值运算符"组"从右到左,有效.含义:分配5 y,留下数字5; 然后将该5分配给x.

这不一样(x = y) = 5,哪个不行!含义:赋值yto x,留下值y; 然后分配5,嗯......,到底是什么?

当你混合不同类型的赋值运算符时,<-绑定比紧=.所以x = y <- 5被解释为x = (y <- 5),这是有道理的情况.

不幸的是,x <- y = 5被解释为(x <- y) = 5,这是不起作用的情况!

请参阅?Syntax?assignOps查看优先级(绑定)和分组规则.



5> Aaron - Rein..:

根据John Chambers的说法,操作员=只允许在"顶层",这意味着它不允许在控制结构中使用if,使下面的编程错误成为非法.

> if(x = 0) 1 else x
Error: syntax error

正如他所写的那样,"在控制表达式中不允许新的赋值形式[=]避免了编程错误(例如上面的例子),这些错误更可能与运算符相等而不是其他S赋值."

你可以设法做到这一点,如果它"与周围的逻辑结构隔离,通过括号或一对额外的括号",那么if ((x = 0)) 1 else x就可以了.

请参阅http://developer.r-project.org/equalAssign.html


啊,是的,我忽略了你说"编程错误".这会导致错误,这实际上是个好消息.并且有理由更喜欢`x = 0`作为赋值而不是`x <-0`!
这是一个常见的错误,`x == 0`几乎总是意味着.
是的,这很好,这会导致一个错误,虽然我画了一个关于什么更喜欢的不同的教训; 我选择尽可能少地使用`=`因为`=`和`==`看起来很相似.
我的意思是,一个*真正*有用的错误检查器会在那里抛出一个错误并说"你有无用的代码总会返回'else`值,你的意思是这样写吗?",但是,这可能是一个管道梦想...
这个例子的呈现方式对我来说太奇怪了.`if(x = 0)1 else x`抛出错误,帮助我找到并纠正错误.`if(x < - 1)1 else x`不会抛出错误并且非常令人困惑.

6> Haim Evgi..:

操作员<-=分配到评估它们的环境中.运算符<-可以在任何地方使用,而运算符=只允许在顶层(例如,在命令提示符下键入的完整表达式中)或作为支撑表达式列表中的子表达式之一.


我认为"顶级"意味着在声明级别,而不是表达级别.所以`x < - 42`本身就是一个陈述; 在`if(x < - 42){}中,它将是一个表达式,并且无效.需要说明的是,这与您是否处于全球环境无关.

7> Denis Rasule..:

这也可以增加对这两个运算符之间差异的理解:

df <- data.frame(
      a = rnorm(10),
      b <- rnorm(10)
)

对于第一个元素,R已经赋值和正确的名称,而第二个元素的名称看起来有点奇怪.

str(df)
# 'data.frame': 10 obs. of  2 variables:
#  $ a             : num  0.6393 1.125 -1.2514 0.0729 -1.3292 ...
#  $ b....rnorm.10.: num  0.2485 0.0391 -1.6532 -0.3366 1.1951 ...

R版本3.3.2(2016-10-31); macOS Sierra 10.12.1


你能不能更详细地解释为什么会发生这种情况/这里发生了什么?(提示:`data.frame`尝试使用提供的变量的名称作为数据框中元素的名称)
这不是一个错误.我试图在上面的评论中暗示答案.设置元素的名称时,R将使用等效的`make.names("b < - rnorm(10)")`.
推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有