作为一门高级语言,R语言拥有独特的语法,比如今天说道的赋值符号。在其他语言里,赋值符合通常用一个等号(=)表示,而在R语言里,承担这个任务的可以是箭头(<-)符号,也可以是等号(=)。这就导致许多R语言初学者,分不清R语言中的赋值到底是使用箭头(<-)还是等号(=)?许多早期学习R的童鞋都比较喜欢使用等号(=)进行赋值。毕竟,简简单单的a = 5用起来比较符合大多数现有语言的习惯。出于对某种赋值方式的偏好,甚至出现了等号党和箭头党,但是到底孰好孰坏,显然争不出任何结果,相对来说更重要的是了解这两者的区别。只有我们深刻理解了其相同与不同之后,才能更好的运用他们。

R语言最开始设计的时候,是采用箭头(<-)作为赋值符号的,这是从APL语言继承而来的(箭头表示赋值,等号表示判断)。之后的S语言也沿用了这个用法,再之后R语言为了保持和S语言的兼容性保留了这个箭头。直到2001年,R的更新版本中 才加入了等号(=)赋值。因此,对于一般的赋值语句,箭头(<-)与 等号(=)在 功能上是没有区别的,可以通用。但是等号(=)的作用有两个:它既可以赋值,也可以传递函数参数(实际上传参可以看作一种特殊形式的赋值,给参数赋值)。通常情况下,如果等号(=)出现在单独的环境中,它就是赋值;如果写在函数的参数位置,它就是传参。如果你在设置参数的时候使用了箭头(<-),那么你会发现在全局变量里,会多出一个和参数名相同的赋值的变量,容易导致歧义和错误,而且占用命名空间。

下面,我们通过几个个例子来具体讲一下这两个函数的区别。

  1. 箭头(<-)和等号(=)赋值在作用域上的不同。
    箭头(<-)创建的变量的作用范围为整个全局环境(Global environment),而等号(=)通常在一个局部环境(Local environment)。例如:

     > rm(x)  ## 如果变量 x 存在的话,先删除此变量> mean(x = 1:10)[1] 5.5> xError: object 'x' not found

    在以上范例里,变量 x 是在函数的作用域里进行声明的,所以它只存在于此函数中,一旦运算完成便“消失”。

     > mean(x <- 1:10)[1] 5.5> x[1]  1  2  3  4  5  6  7  8  9 10

    而采用箭头(<-)赋值,x 变量则出现在了Global Environment 里,并且我们可以调用它。 在此例中,实际上是先构建了x变量,再将x传递给mean函数的第一个参数,我们看到,采用这种方式,程序也正确运行了,但是采用箭头(<-)赋值的方式去传参时要非常小心。可以看下面例子中引起错误地情况。

  2. 箭头(<-)和等号(=)在参数传递时的区别

     > x <- rnorm(100)  # 采用箭头(<-)进行变量赋值> y <- 2*x + rnorm(100)  # 采用箭头(<-)进行变量赋值> lm(formula=y~x)#上面的代码完全等价于下面的代码> x = rnorm(100)  # 采用等号(=)进行变量赋值> y = 2*x + rnorm(100)  # 采用等号(=)进行变量赋值> lm(formula=y~x)

    两段代码中前两行都是赋值语句,分别为x变量和y变量赋值,此时等号(=)与箭头(<-)的功能相同,作用域也相同,因为等号(=)赋值是在全局环境中进行的,而代码第三行中的等号(=)则是调用函数时规定命名参数,这就是通常情况下,我们直接将y~x这个公式直接传递给lm函数的第一个参数,也就是formula参数的用法。如果此时我们将等号(=)替换成箭头(<-),则会在全局环境中定义出一个新的formula变量,然后再将这个变量传递给了lm函数的第一个参数。如果是我们有意这么做的话,就需要保证命名参数的顺序和函数中定义参数的顺序相同,否则就会出现错误,或者将名称相同的变量传递给了错误的参数(但程序可能正常运行),导致结果错误。下面的例子可以突出了这种差别:

     > x <- rnorm(100)> y <- 2*x+rnorm(100)> z <- 3*x+rnorm(100)> data <- data.frame(z,x,y)> rm(x, y, z)    

    此时,环境中已经没有x,y,z变量,就只有变量data可以用来做z~x+y的线性回归。标准写法:

     > lm(formula=z~x+y,data = data)#也可以写成如下形式:> lm(data=data,formula=z~x+y)

    当我们将等号(=)替换成箭头(<-)时,正确的命名参数传递应该按函数参数顺序来逐个传参:

     > lm(formula <- z~x+y, data <- data)Call:lm(formula = formula <- z ~ x + y, data = data <- data)Coefficients:(Intercept)            x            y  0.069869     3.062565     0.007503  > formulaz ~ x + y

    运行也不会出错,但是我们会发现函数实际上是调用的lm(formula = formula <- z ~ x + y, data = data <- data),这时产生了一个新的变量formula到环境中,并且在全局环境中就可以使用(实际上data变量也被更新了)。
    但是如果我们对lm函数的参数顺序不了解或者由于马虎搞错了参数顺序,这个时候就会容易出现错误。

     #错误的写法:> lm(data <- data,formula <- z~x+y)Error in as.data.frame.default(data) : cannot coerce class ""formula"" to a data.frame

    执行时会报告异常,说明data被当作第一个参数formula传递,而formula被当作第二个参数data传递,而参数类型不匹配因而导致异常。因此,在函数的命名参数传递时,尽量不要用箭头(<-),因为既会产生副作用(创建新变量),也无法利用命名参数传递的功能。上面的例子是程序提示了错误,但是有时候程序并不一定会提示错误,就很容易让我们忽视结果实际上是错误的结果。例如:我们构建矩阵时,

     # 构建一个3列的矩阵> matrix(c(1:12),ncol=3)[,1] [,2] [,3][1,]    1    5    9[2,]    2    6   10[3,]    3    7   11[4,]    4    8   12> matrix(c(1:12),ncol<-3)[,1] [,2] [,3] [,4][1,]    1    4    7   10[2,]    2    5    8   11[3,]    3    6    9   12

    我们可以看到,尽管两种方法,都运行成功,且得到了一个矩阵,但是第二个结果是一个错误的结果,此处出错的原因就是,ncol<-3是将3赋值给变量ncol,然后再传递给函数对应位置的参数,而在函数内第二个参数实际上是对应的nrow参数。在实际编写代码时,遇到这种情况,如果我们不注意,就会导致后续所有结果都出错。

  3. 此外,还需要注意的一点就是,在传参中采用箭头(<-)进行赋值的变量只有在需要使用时才会改变其值。例如:

     > a <- 1> f <- function(x) return(TRUE)> f(a <- a + 1); a[1] TRUE[1] 1

    请注意,以上范例里, a 的值并没有改变,也就是a并没有加1,还是原来的a值,这是在函数内部并未用到参数a。这会导致程序里出现一些不可预期的结果并且降低代码可读性,所以不推荐在函数参数里使用箭头(<-)这种赋值方式。在看下面的例子:

     > a <- 1> f <- function(x) {+         if(runif(1)>0.5) TRUE +         else print(x)+ }> 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[1] 2> f(a <- a+1);a[1] TRUE[1] 2> f(a <- a+1);a[1] 3[1] 3

    上述代码中,向函数 f() 传递传递参数 a <- a + 1 后,只有在随机数 runif(1) 小于0.5的时候,a 的值才会改变,即执行+1操作,然后打印a。否则传递TRUE值。因此,因为随机数 runif(1) 的随机性,每次调用函数 f()后 a 的值是不确定的。

现在大家应该清楚了解箭头(<-)和等号(=)的区别了吧!个人建议,大家写赋值语句时采用箭头(<-),传参时使用等号(=)。这也是大部分老师都会强烈推荐的用法。是因为使用箭头(<-)赋值,意义清晰,可以保持代码良好的可读性,尤其是书写复杂函数时,避免造成混乱。Google 的 R style guide(https://google.github.io/styleguide/Rguide.xml)也推荐使用箭头(<-)赋值。 况且有些情况下,只能采用箭头(<-)赋值,例如:system.time(c<-1:10)中就不能使用等号(=)。而从数学的角度来说,等号两边是相等的,即等号左边的等于等号右边的,等号右边的也等于等号左边的。等号本身并没有指向性,因此并没有办法体现”赋值“这一含义。而在R中,箭头(<-)符号生动的阐释了赋值的含义,一个非等号(=)的赋值符从根本上向学习者暗示这样一个真理: 赋值操作与数学上的等于是完全不同的。此外,箭头(<-)符号可以双向赋值,即x <- 10与10 -> x等价。习惯 <- 和 -> 的使用以后,也对后来习惯使用更为复杂的 <<- 以及 ->> 这两个赋值符号(<<-或->>一般用于函数内部,表示给上一层环境中的变量赋值)做好铺垫,而 = 无法实现类似的功能。

另外也有等号党提出异议,认为采用箭头(<-)不如使用等号(=)。例如:如果我想判断一个变量是否小于10,可以写成 x<10;如果我想判断一个变量是否小于-10,然后顺手写成x<-10,这时候就会产生歧义。关于处理负数时产生歧义的说法,只能说是没有正确养成良好的空格习惯造成的,句号逗号后加空格,括号外围加空格,运算符号两边加空格,这些应该是学习代码前就应该懂得的常识。会犯出 a <- 5 和 a < -5 混淆的错误只能说明自己的代码风格糟糕,建议大家Google 的 R style guide(https://google.github.io/styleguide/Rguide.xml )中其他的一些代码写作规则。

Reference

  1. https://www.cnblogs.com/loca/p/4301344.html

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

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

  4. https://stackoverflow.com/questions/1741820/what-are-the-differences-between-and-in-r

  5. http://bbs.pinggu.org/thread-1247151-1-1.html

  6. https://cran.r-project.org/doc/manuals/R-lang.html#Argument-matching

猜你喜欢

10000+:肠道细菌 人体上的生命 宝宝与猫狗 梅毒狂想曲 提DNA发Nature 实验分析谁对结果影响大  Cell微生物专刊

系列教程:微生物组入门 Biostar 微生物组  宏基因组

专业技能:生信宝典 学术图表 高分文章 不可或缺的人

一文读懂:宏基因组 寄生虫益处 进化树

必备技能:提问 搜索  Endnote

文献阅读 热心肠 SemanticScholar Geenmedical

扩增子分析:图表解读 分析流程 统计绘图

16S功能预测   PICRUSt  FAPROTAX  Bugbase Tax4Fun

在线工具:16S预测培养基 生信绘图

科研经验:云笔记  云协作 公众号

编程模板 Shell  R Perl

生物科普  生命大跃进  细胞暗战 人体奥秘

写在后面

为鼓励读者交流、快速解决科研困难,我们建立了“宏基因组”专业讨论群,目前己有国内外150+ PI,1300+ 一线科研人员加入。参与讨论,获得专业解答,欢迎分享此文至朋友圈,并扫码加主编好友带你入群,务必备注“姓名-单位-研究方向-职称/年级”。技术问题寻求帮助,首先阅读《如何优雅的提问》学习解决问题思路,仍末解决群内讨论,问题不私聊,帮助同行。

学习16S扩增子、宏基因组科研思路和分析实战,关注“宏基因组”

点击阅读原文,跳转最新文章目录阅读

你知道R中的赋值符号箭头(-)和等号(=)的区别吗?相关推荐

  1. 你知道R中的赋值符号箭头和等号的区别吗?

    作者:陈亮 单位:中国科学院微生物研究所 你知道R中的赋值符号箭头(<-)和等号(=)的区别吗? 作为一门高级语言,R语言拥有独特的语法,比如今天说道的赋值符号.在其他语言里,赋值符合通常用一个 ...

  2. 通达信标记符号_通达信指标中赋值符号“:”、“=”、“:=”区别?

    求助通达信画线指标显示价格2020-06-04 VV5:=CROSS(MA(C,10),MA(C,13));现价2113:C,COLORYELLOW;压力5261线4102:REF(C*1.0382, ...

  3. 一文学会网络分析——Co-occurrence网络图在R中的实现

    作者:陈亮  单位:中科院微生物所 编者按:在菌群月坛,在军科院听取王军组陈亮博士分享网络分析的经验,不仅使我对网络的背景知识有了更全面的认识,更使我手上一个关于菌根的课题有极大的启示.这么好的知识, ...

  4. R plot图片背景设置为透明_一文学会网络分析——Cooccurrence网络图在R中的实现...

    作者:陈亮  单位:中科院微生物所 编者按:在菌群月坛,在军科院听取王军组陈亮博士分享网络分析的经验,不仅使我对网络的背景知识有了更全面的认识,更使我手上一个关于菌根的课题有极大的启示.这么好的知识, ...

  5. R语言中的复制符号-和=

    对一般的赋值语句,"<-" 与 "=" 功能上无区别  ,但通常我们强推"<-". 原因是等号存在二义性:它既可以赋值,也可以传 ...

  6. R语言 赋值符号 的区别

    R语言赋值可以用=或<-,一般都建议使用<-,那你知道这两个之间的区间吗?那你有没有见过'<-'和'='这种赋值方法吗?今天就来和大家聊聊这基本的赋值符号都有哪些区别. 首先我们来看 ...

  7. [转载] python语言中表示赋值的符号是_Python 语言中 asterisk 符号用法小结

    参考链接: Python中的Inplace与标准运算符 点击上方"蓝字"关注我们 作者 | 孔令昌 编辑 | 张婵 对于 asterisk符号的使用,本文分为预定义(predefi ...

  8. R语言笔记6:在R中写一些简单的函数、functions基础和作用域

    R语言基础系列: 1数据类型(向量.数组.矩阵. 列表和数据框) 2读写数据所需的主要函数.与外部环境交互 3数据筛选--提取对象的子集 4向量.矩阵的数学运算 5控制结构 Your first R ...

  9. r语言向量代码如何创建函数c,R中向量基本操作:创建、运算、访问

    本文含有: 向量的创建与运算 两个方便创建向量的函数:rep()与seq() 如何访问向量中的元素 首先先明白几个要点: R区分大小写,向量A和向量a是两个不同的向量: R可以识别负数,如5+-2可以 ...

最新文章

  1. 77所教育部直属高校公布2020年预算,清华超300亿!
  2. Ubuntu 下配置 SSH服务全过程及问题解决
  3. python祝福祖国代码_国际文交所:9月17日-10月15日《祝福祖国信卡》《澳门爱与祝愿套票》《北京精神封》3个提货转仓公告...
  4. 乌班图14.04安装搜狗输入法
  5. 帝国cms如何安装php模板,2020帝国cms模板安装教程详细介绍
  6. iOS各个版本的新特性介绍
  7. My.Ioc 代码示例——如何使用默认构造参数,以及如何覆盖默认构造参数
  8. python折线图实线虚线_python – matplotlib中的虚线而不是缺失值
  9. ETL调度工具 taskctl-> Designer 设计IDE环境
  10. 使用云服务器的几个安全防护技巧
  11. cox回归模型python实现_生存分析Cox回归模型(比例风险模型)的spss操作实例
  12. 易生活(二)-APP—安卓中评论功能的实现
  13. 复制的eclipse常用快捷键 和 设计模式理解方式
  14. 使用RPA有什么好处
  15. 写出语句的四元式序列
  16. 洛谷月赛T2 P6858[深海少女与胖头鱼]题解
  17. 无法获得锁 /var/lib/dpkg/lock-frontend。锁正由进程 1870(aptd)持有 的解决问题
  18. Java项目:springboot园区管理系统
  19. 《C++沉思录》读书笔记
  20. Ubuntu更换阿里源和清华源

热门文章

  1. 有关容器的六大误区和八大正确场景
  2. Java架构体系学习路线图,这六点尤为重要!
  3. mysql中的if else decode
  4. 计算机组成原理:输入输出系统
  5. class h5 点击后样式变化_css实现选中后变色并且效果不消失
  6. 云桌面可附加桌面文件的程序_给我几分钟,还你一个小清新的电脑桌面
  7. moment 当前日期
  8. java与fabric区块链--fabric-ca-server 注册---(3)
  9. Could not initialize class org.apache.http.impl.conn.ManagedHttpClientConnectionFactory
  10. Jquery中关于动画的一些操作函数