# 这是一行注释
res <- (2 + 4) * 5 / 2 ^ -0.5
res[1] 42.42641
R Language Introduction
R 1 语言是一种自由软件编程语言与操作环境,主要用于统计分析、绘图以及数据挖掘。R 由统计学家罗斯·伊哈卡 2 和罗伯特·杰特曼 3 开发,现在由 R 核心小组负责开发。
R 语言以 S 语言为基础,增加了 Scheme 语言中词法作用域这一机制,使程序员得以将代码中某一对象的适用范围限制到一小段代码之中。R 的后台程序大多由 C 语言、FORTRAN 语言和 R 自己写成。
用户可以用 R 来进行一些基本的统计检验,构建线性及非线性的模型,对时间序列加以分析,或对数据进行分类与聚类分析。R 的另一强项是绘图功能,画出的图表能够达到专业出版物的要求,也可加入数学符号。计算强度较大时,用户可在程序中嵌入 C、C++ 以及 FORTRAN 语言以帮助运算。

R 语言是一种解释型(Interpreter)编程语言,在 R 中变量名和函数名有严格的区分大小写。在 R 语言中赋值符号使用 <-,而非传统的 =。尽管 R 语言支持使用 = 进行赋值操作,但通常这被认为是不地道的语法,当然使用 <- 也会存在一定的问题。x <- 5 则表示将 5 赋值给变量 a,而非表示变量 a 小于 -5。
这就要求用户在编写 R 语言程序时保持良好的代码书写习惯,在合适的位置添加空格,良好的书写习惯应将上述表达式写为 x < -5。R 语言具有类似 C 语言(如 C 、C++、C# 和 Java)的一些特征,例如函数使用大括号包围,同时又具有一些独特之处,例如 R 语言的每行代码结束无需使用 ;,R 语言使用 # 作为注释标记,位于 # 后面的文本将被识别为注释信息而被 R 语言解释器忽略。
R 语言系一种面向对象(object oriented)及函数导向(function directed)的编程语言。因此,对象及函数是成功使用 R 语言的两大关键要素。R 语言是面向对象的,这意味着它符合传统对象的含义。传统对象是指可发送和接收信息的实体。在 R 语言中,所有操作的实体都称之为对象(Object),函数(Function)也不例外。对象可以存储数字,字符串,向量,甚至是函数。R 语言常见的对象类型见右表,用户可以利用 mode() 和 typeof() 函数查看对象的类型或存储模式。
| 类型 | 说明 | 示例 |
|---|---|---|
| integer | 整型数 | 1, 2, 3 |
| double | 浮点数 | 1.0, 2.9, 3.0 |
| logical | 布尔 | TRUE, FALSE |
| character | 字符串 | “ch” |
| complex | 复数 | 1 + 2i |
| builtin | 函数等 | max, min |
| list | 列表 | list(1, 2) |
作为一个函数式编程语言,R 语言中的函数自然占据着至关重要的地位。R 语言中内置很多函数(当然这些函数也包含在包中,这些包在 R 启动时会自动加载,包的相关内容在下节中会详细介绍)。我们日常生活中经常使用到的数学或统计运算基本上都已经含盖了, 如右表所示。
| 函数 | 说明 | 函数 | 说明 |
|---|---|---|---|
log(x) |
以 e 为底 x 的对数 | exp(x) |
x 的指数 |
log10(x) |
以 10 为底 x 的对数 | sum(x) |
x 的加和 |
log(x, base) |
以 base 为底 x 的对数 | prod(x) |
x 的连乘 |
round(x, n) |
四舍五入 x 为 n 位小数 | mean(x) |
x 的均值 |
max(x) |
x 中的最大值 | var(x) |
x 的方差 |
min(x) |
x 中的最小值 | sd(x) |
x 的标准差 |
R 中的扩展包(package)是一种数据,函数和代码的组合,包为 R 语言提供丰富的扩展函数和数据集。在 R 的初始安装版本中已经包括了很多包及数据集, 用户可以从 R 环境菜单栏中的“程序包”选项或利用命令行 installed.packages() 来确认想用的包是否已按经安装。例如:
用户还可以根据自己所处的网络环境指定 CRAN 镜像站点以获得更快速的下载。
数据结构是为用来存储数据和函数操作所产出的对象所设计。我们可认为函数是运算(actions)而数据结构系运算所产出的对象。一个函数的输入参数(arguments)和它所返回的对象是数据结构。因此,我们也可认为函数是数据结构的运算子(operators)。
R 语言提供了 5 个主要的数据结构:向量(Vector),矩阵(Matrix),数组(Array),数据框(Data Frame), 和列表(List)。这些结构系特别设计用于优化数据的存储,存取,处理或分析。数据结构可通过其数据维数(1 维,2 维或 N 维)和数据类型(同构或异构)来区分。
用户何以使用 m[i, j] 访问矩阵 m 的第 i 行第 j 列的元素,使用 m[i, ] 访问矩阵 m 的第 i 行所有列的元素,使用 m[, j] 访问矩阵 m 的所有行第 j 列的元素,同时,矩阵有类似向量的多个元素选择和赋值等操作。
数组(Array)可以理解为一个多维“数组”,在 R 中利用 array() 函数创建数组。array() 函数定义如下:
其中,data 为构造数组所用数据,dim 为维度数,dimnames 为维度名称。
一个 3 维数组的例子:
列表(List)可以理解为 R 中任意对象的一个集合。不同于向量,矩阵和数组,列表可以存储不同类型的数据。在 R 中用户可以利用 list() 创建列表,例如:
数据框(Data Frame)可以理解为 R 中不同数据类型(非任意对象,不包含函数等)的集合。作为 R 中最常用的数据结构之一,在 R 中利用 data.frame() 创建数据框,例如:
id name gender score
1 1 Leo Male 90
2 2 Tom Male 88
3 3 Olivia Female 96
[1] Male Female Male Male
Levels: Female Male
[1] Male Female Male Male
Levels: Female < Male
在 R 语言中,有专门的类型来表示日期和时间,同时提供了日期和时间相关的操作。对于日期,R 中利用 Date 类型进行存储。用户可以利用 as.Date() 函数将一个字符串转化为日期,例如:
对于 Date 类型的日期数据,其背后存储的是距离 1970 年 1 月 1 日的天数。
用户可以指定字符串的格式进行转换,as.Date() 函数默认会尝试使用 %Y-%m-%d 和 %Y/%m/%d 两种格式进行转换,其中 %Y 表示年,%m 表示月,%d 表示天。
对于时间,R 中利用 POSIXct 和 POSIXlt 两种类型进行存储。用户可以利用 as.POSIXct() 将一个字符串转化成时间,例如:
POSIXct 类型数据和 Date 类型数据十分相似,其背后存储的是距离 1970 年 1 月 1 日 00:00:00 的秒数。在将字符串转化为时间时,用户同样可以指定格式,例如:format="%Y-%m-%d %H:%M:%S",其中 %Y,%m 和 %d 与 Date 类型中的格式含义相同,%H 表示时,%M 表示分,%S 表示秒。除此之外,用户还可以指定时区,例如:tz="UTC"。
POSIXlt 类型数据背后利用一个列表存储时间,因此 POSIXlt 类型的相关操作较少,但是比较方便获取时间中的元素。
[1] "sec" "min" "hour" "mday" "mon" "year" "wday" "yday"
[9] "isdst" "zone" "gmtoff"
对于日期和时间,R 提供了几个通用处理函数。
时间序列可以理解为一个数值型元素的向量,因为时间序列应用在很多场景中,因此 R 中为其提供了一个单独的类型来管理。在 R 中利用 ts() 函数创建时间序列,ts() 函数定义如下:
| 参数 | 说明 |
|---|---|
data |
构造时间序列所需数据 |
start |
时间序列的起点和偏移量(可省略) |
end |
时间序列的终点和偏移量(可省略) |
frequency |
每个观察点的数据采样量 |
| 参数 | 说明 |
|---|---|
deltat |
观察点内采样点距离(1/12 表示每个观察点之间有 12 个数据,与 frequency 保留一个) |
ts.eps |
时间序列的比较允许误差(当时间序列的 freauency 的绝对误差小于 ts.eps 时,认为相同) |
在进行类型转换前,首先我们需要清楚待转换的对象是什么类型。R 语言提供了一系列函数判断对象的类型,这些函数的特点是以 is. 开头,例如:
同样,R 语言也提供了一系列的函数用于对象的类型转换,这些函数的特点是以 as. 开头。在 R 语言中,不是所有的类型之间都能够相互转换。例如:数值型对象可以向字符型对象转换,但字符型对象并不一定能够转换成合理的数值型对象。
存储类型的转换:
| 函数 | 说明 |
|---|---|
as.integer() |
转换为整数(当转换为整数时,小数部分将被删除,非四舍五入。) |
as.double() |
转换为浮点数 |
as.numeric() |
转换为数值型(同 as.double(),S4 方法) |
as.character() |
转换为字符型 |
as.logical() |
转换为布尔型 |
数据结构的转换:
| 函数 | 说明 |
|---|---|
as.vector() |
转换为向量 |
as.matrix() |
转换为矩阵 |
as.array() |
转换为数组 |
as.list() |
转换为列表 |
as.data.frame() |
转换为数据框 |
进行数据类型转换时,并不一定会得到所期望的结果。
向量转换为矩阵还可以利用 cbind() 和 rbind() 两个函数。cbind() 是将向量按照列拼接成矩阵,rbind() 是将向量按照行拼接成矩阵。
在 R 语言中除了数值,字符串等常量外,还有 4 个特殊常量:NULL,NA,Inf 和 NaN。
尽管编码格式不是强制性的要求,但是良好的编码风格可以使写成的代码更易阅读。
文件名应尽量全面的表达所包含的内容,例如:一个用于计算平均成绩的 R 脚本的文件可以取名为:calculate_avg_score.R
在很多语言的变量和函数编码风格中驼峰命名法和匈牙利命名法都已经被采用,但在 R 中我们更加倾向使用 R 特有的编码风格。R 语言中,变量名称中字母全部采用小写,单词之间用 . 或 _ 连接,例如:平均成绩可以表示为:avg.score 或 avg_score
R 语言中,函数名采用大驼峰式命名法,即每一个单词的首字母大写,单词之间无空格和连接符,例如:计算总成绩的函数名可以表示为:CalculateTotalScore
同其他编程语言一样,单行建议不超过 80 个英文字符。不同层级的代码需要缩进,一般建议使用 4 个空格而不是使用 Tab,更不可两者混用。在运算符(+,-,*,/ 等)和赋值符号(<-)的前后建议用 1 个空格分割,如:v <- 5 + 4 / 2。
在调用函数指定参数名时,= 的前后可以不必须用空格分割。同英文书写规范类似,R 语言在 , 前不加空格,在后面加 1 个空格作为分隔,例如:mean(score[, 1])。
在控制语句中,小括号应用关键字保持 1 个空格的间隔,同时花括号应与前面的内容保持 1 个空格的间隔。当不同条件下仅有一行代码时,建议用户也使用花括号将其包围,这样可以避免当用户添加代码时忘记添加花括号。
文件注释位于 R 脚本的开头,主要包括版权信息,作者信息,文件内容描述,日期等相关信息。建议的示例:
# -----------------------------------------------------------------
# This R script is lincensed under GPL.
# http://www.gnu.org/licenses/gpl.html
# -----------------------------------------------------------------
# Description:
# This R script is used for calculating average score
# Author: Leo Van
# Date: 2025-12-21
# -----------------------------------------------------------------函数注释位于函数定义的上方,主要包括函数的描述,参数值和返回值等相关信息。建议的示例:
#' Description:
#' Calculate the average score of specific class and subject
#'
#' @param class Name of class
#' @param subject Name of subject
#' @param na.omit Omit NA values or not (Default: TRUE)
#' @return Average score of specific class and subject.
CalculateAvgScore <- function(class, subject, na.omit=TRUE) {
# detail of function
}在 R 脚本中,作者有必要在合适的位置(例如:不同功能块之前)作出相关说明。同时对于后续要进一步改进或修正的部分,也应做出恰当的注释。建议的示例:
除了要保持良好的注释习惯以外,合理的排版(代码书写顺序)同样至关重要。一个合理的顺序能够帮助 R 脚本的其他阅读者很快的理解所要表达的意图。
require() 或 library()source()除了上述的 R 编码风格建议外,还有一些需要用户在使用中注意事项:
<-,而非 =(尽管支持)。tryCatch() 进行处理,避免造成程序退出。stop(),打印问题信息,并返回上层代码。_test 以作标识。版权所有 © 范叶亮 Leo Van