1.3 R的使用
R是一种区分大小写的解释型语言。你可以在命令提示符(>
)后每次输入并执行一条命令,或者一次性执行写在脚本文件中的一组命令。R中有多种数据类型,包括向量、矩阵、数据框(与数据集类似)以及列表(各种对象的集合)。我们将在第2章中讨论这些数据类型。
R中的多数功能是由程序内置函数和用户自编函数提供的,一次交互式会话期间的所有数据对象都被保存在内存中。一些基本函数是默认直接可用的,而其他高级函数则包含于按需加载的程序包中。
R语句由函数和赋值构成。R使用 <-
,而不是传统的 =
作为赋值符号。例如,以下语句:
x <- rnorm(5)
创建了一个名为x
的向量对象,它包含5个来自标准正态分布的随机偏差。
注意 R允许使用
=
为对象赋值。但是这样写的R程序并不多,因为它不是标准语法,某些情况下,用等号赋值会出现问题,R程序员可能会因此取笑你。你还可以反转赋值方向。例如,rnorm(5) -> x
与上面的语句等价。重申一下,使用等号赋值的做法并不常见,在本书中不推荐使用。
注释由符号 #
开头。在 #
之后出现的任何文本都会被R解释器忽略。
1.3.1 新手上路
如果你使用的是Windows,从开始菜单中启动R。在Mac上,则需要双击应用程序文件夹中的R图标。对于Linux,在终端窗口中的命令提示符下敲入R并回车。这些方式都可以启动R(R界面参见图1-3)。
图1-3 Windows中的R界面
让我们通过一个简单的虚构示例来直观地感受一下这个界面。假设我们正在研究生理发育问题,并收集了10名婴儿在出生后一年内的月龄和体重数据(见表1-1)。我们感兴趣的是体重的分布及体重和月龄的关系。 表1-1 10名婴儿的月龄和体重
年龄(月) | 体重(kg) |
---|---|
01 | 4.4 |
03 | 5.3 |
05 | 7.2 |
02 | 5.2 |
11 | 8.5 |
09 | 7.3 |
03 | 6.0 |
09 | 10.4 |
12 | 10.2 |
03 | 6.1 |
*以上为虚构数据。
可以使用函数c()
以向量的形式输入月龄和体重数据,此函数可将其参数组合成一个向量或列表。然后用其他函数获得体重的均值和标准差,以及月龄和体重的相关度,最后用图形展示月龄和体重的关系,这样就可以用可视化的方式检查其中可能存在的趋势。如代码清单1-1所示,函数q()
将结束会话并允许你退出R。
代码清单1-1 一个R会话示例
> age <- c(1,3,5,2,11,9,3,9,12,3)
> weight <- c(4.4,5.3,7.2,5.2,8.5,7.3,6.0,10.4,10.2,6.1)
> mean(weight)
[1] 7.06
> sd(weight)
[1] 2.077498
> cor(age,weight)
[1] 0.9075655
> plot(age,weight)
> q()
从代码清单1-1中可以看到,这10名婴儿的平均体重是7.06 kg,标准差为2.08 kg,月龄和体重之间存在较强的线性关系(相关度 = 0.91)。这种关系也可以从图1-4所示的散点图中看到。不出意料,随着月龄的增长,婴儿的体重也趋于增加。
图1-4 婴儿体重(千克)和年龄(月)的散点图
散点图1-4的信息量充足,但略过“功利”,也不够美观。接下来的几章里,我们会讲到如何自定义图形以契合需要。
小提示 若想大致了解R能够作出何种图形,在命令行中运行
demo(graphics)
即可。生成的部分图形如图1-5所示。其他的演示还有demo(Hershey)
、demo(persp)
和demo(image)
。要看到完整的演示列表,不加参数直接运行demo()
即可。
图1-5 函数
demo()
绘制的图形示例
1.3.2 获取帮助
R提供了大量的帮助功能,学会如何使用这些帮助文档可以在相当程度上助力你的编程工作。R的内置帮助系统提供了当前已安装包中所有函数1的细节、参考文献以及使用示例。帮助文档可以通过表1-2中列出的函数进行查看。
1 确切地说,这里的“所有”是指那些已导出的(exported)、对用户可见的函数。——译者注 表1-2 R中的帮助函数
函 数 | 功 能 |
---|---|
help.start() | 打开帮助文档首页 |
help("foo") 或?foo | 查看函数foo 的帮助(引号可以省略) |
help.search("foo") 或??foo | 以foo 为关键词搜索本地帮助文档 |
example("foo") | 函数foo 的使用示例(引号可以省略) |
RSiteSearch("foo") | 以foo 为关键词搜索在线文档和邮件列表存档 |
apropos("foo", mode="function") | 列出名称中含有foo 的所有可用函数 |
data() | 列出当前已加载包中所含的所有可用示例数据集 |
vignette() | 列出当前已安装包中所有可用的vignette文档 |
vignette("foo") | 为主题foo 显示指定的vignette文档 |
函数help.start()
会打开一个浏览器窗口,我们可在其中查看入门和高级的帮助手册、常见问题集,以及参考材料。函数RSiteSearch()
可在在线帮助手册和R-Help邮件列表的讨论存档中搜索指定主题,并在浏览器中返回结果。由函数vignette()
函数返回的vignette文档一般是PDF格式的实用介绍性文章。不过,并非所有的包都提供了vignette文档。不难发现,R提供了大量的帮助功能,学会如何使用这些帮助文档,毫无疑问地会有助于编程。我经常会使用?
来查看某些函数的功能(如选项或返回值)。
1.3.3 工作空间
工作空间(workspace)就是当前R的工作环境,它储存着所有用户定义的对象(向量、矩阵、函数、数据框、列表)。在一个R会话结束时,你可以将当前工作空间保存到一个镜像中,并在下次启动R时自动载入它。各种命令可在R命令行中交互式地输入。使用上下方向键查看已输入命令的历史记录。这样我们就可以选择一个之前输入过的命令并适当修改,最后按回车重新执行它。
当前的工作目录(working directory)是R用来读取文件和保存结果的默认目录。我们可以使用函数getwd()
来查看当前的工作目录,或使用函数setwd()
设定当前的工作目录。如果需要读入一个不在当前工作目录下的文件,则需在调用语句中写明完整的路径。记得使用引号闭合这些目录名和文件名。
用于管理工作空间的部分标准命令见表1-3。 表1-3 用于管理R工作空间的函数
函 数 | 功 能 |
---|---|
getwd() | 显示当前的工作目录 |
setwd("mydirectory") | 修改当前的工作目录为mydirectory |
ls() | 列出当前工作空间中的对象 |
rm(objectlist) | 移除(删除)一个或多个对象 |
help(options) | 显示可用选项的说明 |
options() | 显示或设置当前选项 |
history(#) | 显示最近使用过的#个命令(默认值为25) |
savehistory("myfile") | 保存命令历史到文件myfile 中(默认值为.Rhistory ) |
loadhistory("myfile") | 载入一个命令历史文件(默认值为.Rhistory ) |
save.image("myfile") | 保存工作空间到文件myfile 中(默认值为.RData ) |
save(objectlist, file="myfile") | 保存指定对象到一个文件中 |
load("myfile") | 读取一个工作空间到当前会话中(默认值为.RData ) |
q() | 退出R。将会询问你是否保存工作空间 |
要了解这些命令是如何运作的,运行代码清单1-2中的代码并查看结果。
代码清单1-2 用于管理R工作空间的命令使用示例
setwd("C:/myprojects/project1")
options()
options(digits=3)
x <- runif(20)
summary(x)
hist(x)
savehistory()
save.image()
q()
首先,当前工作目录被设置为C:/myprojects/project1,当前的选项设置情况将显示出来,而数字将被格式化,显示为具有小数点后三位有效数字的格式。然后,我们创建了一个包含20个均匀分布随机变量的向量,生成了此数据的摘要统计量和直方图。最后,命令的历史记录保存到文件.Rhistory中,工作空间(包含向量x
)保存到文件.RData中,会话结束。
注意setwd()
命令的路径中使用了正斜杠。R将反斜杠(\
)作为一个转义符。即使在Windows平台上运行R,在路径中也要使用正斜杠。同时注意,函数setwd()
不会自动创建一个不存在的目录。如果必要的话,可以使用函数dir.create()
来创建新目录,然后使用setwd()
将工作目录指向这个新目录。
在独立的目录中保存项目是一个好主意。我通常会在启动一个R会话时使用setwd()
命令指定到某一个项目的路径,后接不加选项的load()
命令。这样做可以让我从上一次会话结束的地方重新开始,并保证各个项目之间的数据和设置互不干扰。在Windows和Mac OS X平台上就更简单了。跳转到项目所在目录并双击保存的镜像文件即可。这样做可以启动R,载入保存的工作空间,并设置当前工作目录到这个文件夹中。
1.3.4 输入和输出
启动R后将默认开始一个交互式的会话,从键盘接受输入并从屏幕进行输出。不过你也可以处理写在一个脚本文件(一个包含了R语句的文件)中的命令集并直接将结果输出到多类目标中。
- 输入
函数source("filename")
可在当前会话中执行一个脚本。如果文件名中不包含路径,R将假设此脚本在当前工作目录中。举例来说,source("myscript.R")
将执行包含在文件myscript.R中的R语句集合。依照惯例,脚本文件以.R作为扩展名,不过这并不是必需的。
- 文本输出
函数sink("filename")
将输出重定向到文件filename
中。默认情况下,如果文件已经存在,则它的内容将被覆盖。使用参数append=TRUE
可以将文本追加到文件后,而不是覆盖它。参数split=TRUE
可将输出同时发送到屏幕和输出文件中。不加参数调用命令sink()
将仅向屏幕返回输出结果。
- 图形输出
虽然sink()
可以重定向文本输出,但它对图形输出没有影响。要重定向图形输出,使用表1-4中列出的函数即可。最后使用dev.off()
将输出返回到终端。
表1-4 用于保存图形输出的函数
函 数 | 输 出 |
---|---|
pdf("filename.pdf") | PDF文件 |
win.metafile("filename.wmf") | Windows图元文件 |
png("filename.png") | PBG文件 |
jpeg("filename.jpg") | JPEG文件 |
bmp("filename.bmp") | BMP文件 |
postscript("filename.ps") | PostScript文件 |
让我们通过一个示例来了解整个流程。假设我们有包含R代码的三个脚本文件script1.R、script2.R和script3.R。执行语句:
source("script1.R")
将会在当前会话中执行script1.R中的R代码,结果将出现在屏幕上。
如果执行语句:
sink("myoutput", append=TRUE, split=TRUE)
pdf("mygraphs.pdf")
source("script2.R")
文件script2.R中的R代码将执行,结果也将显示在屏幕上。除此之外,文本输出将被追加到文件myoutput中,图形输出将保存到文件mygraphs.pdf中。
最后,如果我们执行语句:
sink()
dev.off()
source("script3.R")
文件script3.R中的R代码将执行,结果将显示在屏幕上。这一次,没有文本或图形输出保存到文件中。整个流程大致如图1-6所示。
图1-6 使用函数source()
进行输入并使用函数sink()
进行输出
R对输入来源和输出走向的处理相当灵活,可控性很强。在1.5节中,我们将学习如何在批处理模式下运行R程序。