Menu

R 语言基础语法:5 分钟入门

R 语法的核心:用 <- 赋值,表达式与自动打印,带具名参数的函数调用,以及“一切皆向量”的规则。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

表达式与自动打印

R 是一门表达式语言:你写的几乎每一行都会产生一个值。在控制台中,单独输入的表达式会被求值,结果自动打印出来,不需要 print():

每个结果前面都有 [1],这是 R 在告诉你显示的第一个值的位置,也是 R 以向量方式思考的第一个迹象(下面会细说)。自动打印有一个第一天就值得知道的陷阱:它只适用于顶层的单独表达式。同样的表达式放在函数体或 for 循环里,什么都不会打印,所以脚本中需要看到的输出,都要显式地用 cat() 或 print()。

赋值:箭头

R 的赋值运算符是 <-,一个指向接收值的名字的箭头:

radius <- 5 读作“radius 得到 5”。没错,顶层赋值用 = 也可以;也没错,新手都会问为什么有人宁愿多打一个字符。答案是一个有约束力的约定:所有主流风格指南、基础 R 文档,以及你将来读到的几乎所有 R 代码,都用 <- 赋值,而把 = 留给一个特定的用途:在函数调用中给参数命名(见下一节)。遵循这个约定,两种操作在视觉上就能区分开。在 RStudio 中,按 Alt+-(macOS 上是 Option+-)就能输入这个箭头。

注意,赋值不会自动打印,area <- 78.5 只是悄悄地保存这个值。所以上面的代码片段需要 print()。

大小写敏感

R 严格区分大小写,不管是你自己创建的名字,还是语言自带的名字:

这是两个不同的变量。同样,mean() 是一个函数,而 Mean() 根本不存在。当 R 给你报 object 'x' not found 或 could not find function 时,先检查大小写,这是初学者最常犯的错误。

函数调用与具名参数

函数用括号调用,参数之间用逗号分隔。参数可以按位置匹配,也可以按名字匹配,或者两者混用:

seq() 这个调用展示了 R 的具名参数语法,这正是 = 派上用场的地方:在调用内部,name = value 给参数加上标签。具名参数让你不必记住参数的顺序,还能让调用本身就说明自己在做什么;seq(0, 100, 25) 的效果完全一样,但告诉读者的信息更少。实际的约定是:第一个参数(通常是数据)按位置传,其余的都写上名字。

查看任何函数的帮助只需一步:在控制台输入 ?seq,就会打开它的文档。

一切皆向量

让 R 和其他语言感觉不一样的关键思想是:R 中没有单独的数字。就连 5 也是一个长度为一的向量,而运算会对整个向量逐元素进行:

一个循环都没有,但每个元素都被转换了。在大多数语言里,这需要 for 循环迭代三次;在 R 里,这只是算术运算。这就是向量化,它影响着一切:比较运算符、字符串函数和数学函数都是这样工作的。这也是为什么地道的 R 代码中循环比你想象的少得多;完整的介绍见向量。

大括号与代码块

多行的代码体,比如 if、循环和函数的代码体,用大括号 {} 组合在一起:

有两点要注意。条件写在括号里,就是普通的 if,不是 if:,也不是 if ... then。另外,和 Python 不同,R 中的缩进没有任何语法意义:代码块由大括号决定,缩进是给人看的。单行代码省略大括号是合法的,但这是编辑代码时出 bug 的经典来源;干脆一直写上大括号。

空白与分号

R 会忽略多余的空白,换行就结束一条语句,不需要分号:

能跨行书写,是因为第 3 行以 + 结尾,R 知道这个表达式还没结束。这是拆分长行时唯一要记住的规则:在运算符或逗号之后换行,而不要在它们之前换行,否则 R 会认为第一行已经是完整的语句。分号的存在只是为了把两条语句塞进一行(a <- 1; b <- 2):合法,但不推荐,而且很容易避免。

风格:R 代码是怎么写的

除了语法,R 社区还有很强的约定(写在 tidyverse 风格指南中,整个生态的大部分都遵循它):

  • 用 <- 赋值,= 只用于调用中的参数。
  • snake_case 命名:写 monthly_revenue,而不是 monthlyRevenue 或 monthly.revenue。R 的名字中可以有点号,但最好避免,因为它和 R 内部使用的一种命名模式冲突。
  • 运算符两边和逗号后面加空格(写 x <- a * 2,而不是 x<-a*2)。
  • 大括号内部用四个空格缩进(有些团队用两个,选一种并保持一致)。
  • 每行一条语句。

这些都不是解释器强制要求的,但所有读你代码的人都会这么要求你。关于命名的部分,会在变量中继续讲。

要点回顾

  • R 会对表达式求值,并在控制台中自动打印单独的表达式,但在函数或循环内部不会。
  • 用 <-(“得到”)赋值;= 只用于在函数调用中给参数命名。
  • R 完全区分大小写,早期遇到的大多数 “not found” 错误都是大小写写错了。
  • 一切皆向量,运算逐元素进行:c(1, 2, 3) * 2 就是 2 4 6,不需要循环。
  • 大括号定义代码块,换行结束语句,snake_case 加上空格约定,能让你的代码读起来和其他人的一样。

下一篇:注释,如何给 R 代码加注释,以及 R 没有块注释语法时该怎么办。

常见问题

R 中的 <- 是什么意思?

<- 是 R 的赋值运算符:x <- 5 把值 5 存到名字 x 下面。可以读作“得到”。在顶层,= 也能赋值,但社区的约定(所有主流风格指南都这样要求)是用 <- 赋值,= 只用于在函数调用中给参数命名。

R 区分大小写吗?

区分,而且完全区分。total、Total 和 TOTAL 是三个不同的名字,把 mean(x) 写成 Mean(x) 会直接报错,而不只是警告。“could not find function”或“object not found”错误,很多时候只是大小写写错了。

R 需要分号吗?

不需要。换行就结束了一条语句。只有想把两条语句挤在同一行时(a <- 1; b <- 2)才需要分号,而风格指南本来也不建议这样做。每行写一条语句,就再也不用操心分号了。

R 是向量化的,这是什么意思?

R 的基本运算会一次作用于整个向量。c(1, 2, 3) * 2 的结果是 2 4 6,乘法作用在每个元素上,不需要循环。在其他语言里要写成 for 循环的代码,在 R 中大多只是一个表达式。

Coddy 编程语言插图

和 Coddy 一起学编程

开始