R 语言赋值运算符:`<-` , `=`, `<<-`
<- 与 = 间的区别
<- 与 = 在大部分情况下是应该可以通用的。并且,相对于 <<- 运算符,它们的赋值行为均在它们自身的环境层(environment hierarchy)中进行。
R语言中,<- 与 = 这两个赋值运算符最主要的区别在于两者的作用域不同。大家可以从下面的例子感受一下。
好多好多人喜欢用的 =
貌似许多早期学习R的童鞋都比较喜欢使用 = 进行赋值。毕竟,简简单单的a = 5用起来比较符合大多数现有语言的习惯。
> rm(x) ## 如果变量 x 存在的话,删除此变量
> mean(x = 1:10)
[1] 5.5
> x
Error: object 'x' not found
在以上范例里,变量 x 是在函数的作用域里进行声明的,所以它只存在于此函数中,一旦运算完成便“消失”。

而对于 <-
使用 <- 的运算结果则如下:
> mean(x <- 1:10)
[1] 5.5
> x
[1] 1 2 3 4 5 6 7 8 9 10
这一次, Global Environment 里出现了 x 变量

在什么情况下, <- 赋值会成立?
在以上代码里,你可能会认为计算机对上述语句进行的处理是“将 1:10 赋值给 x , 然后计算 x 的均值。”在某些语言里,计算机的确是如此处理的,比如说 C 。但是在R语言中,却不是这样的。见下例。
> a <- 1
> f <- function(a) return(TRUE)
> f <- f(a <- a + 1); a
[1] TRUE
[1] 1
请注意,以上范例里, a 的值并没有改变!!在 R 中,在参数中进行赋值的变量只有在需要进行评估时才会改变其值。(也许,大家可以类比一下逻辑短路?1 < 0 && 2 == 1)这会导致程序里出现一些不可预期的结果并且降低代码可读性,所以并不推荐在函数参数里使用这一种赋值方式(事实上,函数参数弄那么复杂也是太无聊了了吧)
> a <- 1
> f <- function(a) {
+ if(runif(1)>0.5) TRUE
+ else a
+ }
> f(a <- a+1);a
[1] TRUE
[1] 1
> f(a <- a+1);a
[1] TRUE
[1] 1
> f(a <- a+1);a
[1] TRUE
[1] 1
> f(a <- a+1);a
[1] 2
> f(a <- a+1);a
[1] TRUE
[1] 2
> f(a <- a+1);a
[1] 3
上述代码中,向函数 f() 传递传递参数 a <- a + 1 后,只有在随机数 runif(1) 小于0.5的时候,a 的值才会改变,即执行+1操作。否则传递TRUE值。因此,因为随机数 runif(1) 的随机性,每次调用函数 f()后 a 的值是不确定的。
BUT!
并不是说 <-看起来复杂所以就索性不用它了。事实上,正如上文所说,如果不是有人会这么无聊在R 语言里进行数据分析时用 <- 弄个这么坑爹的函数参数,这个赋值号的意义本身是很清晰的。
<- 长得像箭头,实质上也是个箭头,如果觉得从右向左赋值让你觉得不爽的话,用 -> 甚至都是可以的。而那个传统的 = 号,在 R 里实质上是退化了的,其在规范的 R 语言代码里其实一般是作为为子集赋“name”的存在。
一个较为规范的赋值号使用方式应该是酱紫的。
> a <- list(hello = 1, world = 2 ) ##如果 <- 换成 = 得多混乱……
> a
$hello
[1] 1
$world
[1] 2
> a$hello
[1] 1
> a[["world"]] ## '$' 与 '[["..."]]'是两种不同的引用name的方式~~
[1] 2
<<— 运算符,向上一环境层写入变量
在 R 语言中,处在某一个环境层的代码都拥有读入上一环境层的变量的权限,但相反地,若只通过标准的赋值运算符 <- ,是无法向上一环境层写入变量的。若想在上一环境层进行赋值行为,即向上一层次写入变量,则需要用到 <<- (superassignment)运算符啦~
对非局部变量进行写入操作
看,灰机!
> plusx <- function(x){
+ a <<- 1 + x
+ b <- 2 + x
+ x <- x * 2
+ }
> a
Error: object 'a' not found
> b
Error: object 'b' not found
> x <- 1
> plusx(x)
> a
[1] 2
> b
Error: object 'b' not found
> x
[1] 1
分析一下函数two() 中的三个变量 x, a, b
- x:作为plusx()的实际参数,调用时其值1复制到形参 x ,但形参仍为局部变量,故作为全局变量的 x 值不变
- a:在调用函数plusx() 之前, 变量 a 和 b 是根本就不存在的。直到调用了plusx()后,a 才在出现。并且,由于plusx()的上一环境层即为顶层环境(Global Environment), 可直接在变量框内看见 a。
- b:为局部变量,正如上文所说,
<-进行的赋值仅在当前环境层进行。
此例表明, 通过 <<- 赋值符,plusx()函数在顶层环境写入了变量 a .
一些注意事项
一般说来, <<- 多用于在顶层环境中写入变量。然而需要注意的是,以 <<- 执行赋值时,会一直向上直至顶层进行变量查找。若在查找过程中寻找到该名称的变量,就会进行赋值操作。否则,将在顶层环境中创建变量并赋值。
> glob <- function(){
+ d <- 5
+ nxt1 <- function(){d <<- e + 1}
+ e <- 2
+ nxt1()
+ d
+ }
> glob()
[1] 3
> d
Error: object 'd' not found
此处,对 d 运用了 <<- 进行赋值时,由于nxt1()的上一环境层中出现了变量 d ,故赋值在glob()环境层进行,而非顶层(Global Environment)
对比以下代码:
> glob <- function(){
>
+ ##区别在这里,少了一行' d <- 5'
+
+ nxt1 <- function(){d <<- e + 1}
+ e <- 2
+ nxt1()
+ d
+ }
> glob()
[1] 3
> d
[1] 3
此处,由于glob()环境中没有 d 变量的存在,在 nxt1() 中使用 <<- 赋值时变量 d 成为顶层变量。
参考资料
[1]某论坛中贴出的关于的
<-与=区别的英文例子http://www.itongji.cn/tag/Ryuyan_2417_1.html
[2]<<-赋值号部分主要参考于The Art of R Programming(《R语言编程艺术》)7.8 Writing Upstair
R 语言赋值运算符:`<-` , `=`, `<<-`的更多相关文章
- R语言笔记:快速入门
1.简单会话 > x<-c(1,2,4) > x [1] 1 2 4 R语言的标准赋值运算符是<-.也可以用=,不过不建议用它,有些情况会失灵.其中c表示连接(concaten ...
- 数据攻略●R语言自述
(注明:以下文章均在Linux操作系统下执行) 一.R语言简介 R语言是用于统计分析,图形表示和报告的编程语言和软件环境.R语言由Ross Ihaka和Robert Gentleman在新西兰奥克兰大 ...
- R语言手册
在R的官方教程里是这么给R下注解的:一个数据分析和图形显示的程序设计环境(A system for data analysis and visualization which is built bas ...
- R语言编程艺术(3)R语言编程基础
本文对应<R语言编程艺术> 第7章:R语言编程结构: 第9章:面向对象的编程: 第13章:调试 ============================================== ...
- R语言运算符
运算符是一个符号,它告诉编译器执行特定的数学或逻辑操作. R语言丰富的内置运算符,并提供以下类型的运算符. 运算符类型 在R编程中有以下类型的运算符 - 算术运算符 关系运算符 逻辑运算符 赋值运算符 ...
- 《R语言实战》读书笔记--第一章 R语言介绍
1.典型的数据分析过程可以总结为一下图形: 注意,在模型建立和验证的过程中,可能需要重新进行数据清理和模型建立. 2.R语言一般用 <- 作为赋值运算符,一般不用 = ,原因待考证.用-> ...
- R语言 运算符
R语言运算符 运算符是一个符号,通知编译器执行特定的数学或逻辑操作. R语言具有丰富的内置运算符,并提供以下类型的运算符. 运算符的类型 R语言中拥有如下几种运算符类型: 算术运算符 关系运算符 逻辑 ...
- R语言入门 (有其他编程语言基础)
慢慢才意识到概率统计的重要性,当时学的时候只知道很重要,是机器学习基础啥的,但是却没有真正意识到( ╯□╰ ).我现在的理解是,统计学习可以从大数据中挖掘出规律(其实和数据挖掘还是很相关的),在科研工 ...
- R语言作为BI中ETL的工具
R语言作为BI中ETL的工具,增删改 R语言提供了强大的R_package与各种数据库进行数据交互. 外加其强大数据变换清洗函数,为ETL提供一条方便快捷的道路. RODBC ROracal RMys ...
随机推荐
- QQ空间动态内容,好友信息,点赞爬虫脚本
一.安装基础的软件包: 1.准备好火狐浏览器,并下载geckodriver,将geckodriver加入到环境变量:下载geckodriver的地址:https://pan.baidu.com/s/1 ...
- 和为定值的m个数
和为定值的m个数 np 问题(时间复杂度o(2**n)) code1: 暴力递归 解决 只有正数的情况 class Solution { private List<List<Integer ...
- Python框架之Tornado(请求阶段)
上图是tornado程序启动以及接收到客户端请求后的整个过程,对于整个过程可以分为两大部分: 启动程序阶段,又称为待请求阶段(上图1.2所有系列和3.0) 接收并处理客户端请求阶段(上图3系列) 简而 ...
- CSS3自定义滚动条样式 之 -webkit-scrollbar
有没有觉得浏览器自带的原始滚动条很不美观,同时也有看到很多网站的自定义滚动条显得高端,就连chrome32.0开发板都抛弃了原始的滚动条,美观多了.那webkit浏览器是如何自定义滚动条的呢? 前言 ...
- Linux系统crontab定时调度Python脚本
Linux系统crontab定时调度Python脚本 一.Python脚本随Linux开机自动运行 #Python脚本:/home/edgar/auto.py #用root权限编辑以下文件:/etc/ ...
- MySQL性能优化之max_connections参数
很多开发人员都会遇见”MySQL: ERROR 1040: Too many connections”的异常情况,造成这种情况的一种原因是访问量过高,MySQL服务器抗不住,这个时候就要考虑增加从服务 ...
- 20145201 《Java程序设计》第一周学习总结
# 20145201 <Java程序设计>第一周学习总结 ## 教材学习内容总结 万事开头难,终于开始学习了Java.寒假的时候看到老师的要求确实有点慌,但是这周翻开书,从书本知识第一行学 ...
- How to create and manage configuration backups in Internet Information Services 7.0
https://support.microsoft.com/en-us/help/954872/how-to-create-and-manage-configuration-backups-in-in ...
- “玲珑杯”ACM比赛 Round #13 B -- 我也不是B(二分排序)
题意:开始有一个空序列s,一个变量c=0,接着从左往右依次将数组a中的数字放入s的尾部,每放一个数字就检测一次混乱度K,当混乱度k大于M时就清空序列并让c=c+1 K = Bi * Vi(1<= ...
- Standard 1.1.x VM与Standard VM的区别
在Eclipse或MyEclipse中要设置Installed JREs时,有三个选择: - Execution Environment Description - Standard 1.1.x VM ...