什么是包
包(package)是一组函数、文档,有时还带有数据,用来扩展 R 的功能。基础 R 提供了向量、模型和绘图;其他所有功能都来自包,而这个“其他所有功能”的范围非常大。CRAN(Comprehensive R Archive Network)上托管着大约 20,000 个包,每一个在发布前都要通过 CRAN 的提交检查。正是这个仓库让 R 在数据工作中始终保持竞争力:不管你要做什么分析,很可能已经有人把它做成了包。
CRAN 不是唯一的来源。Bioconductor 托管着生物信息学的生态,很多还在开发中的包放在 GitHub 上(可以用 remotes::install_github() 安装)。不过作为初学者,你可以把 CRAN 当作默认来源,其他来源等到某个 README 让你用时再说。
有少数几个包是随 R 一起安装的(stats、utils、graphics 等),并且会自动加载,所以 mean() 和 plot() 可以直接用。其他所有包都要走下面这两步。
install.packages() 装一次,library() 每次会话都要加载
这是初学者最常见的困惑,所以这里尽量讲清楚。让一个包能用起来,是两个不同的操作,生效的时间范围也不同:
install.packages("dplyr") # ONCE per machine: downloads from CRAN and installs
library(dplyr) # EVERY session: loads it so your code can use it
install.packages("dplyr")就像买一本书:只做一次,从此它就放在你的书架上(你的硬盘里)。注意这里的引号:你传入的包名是一个字符串。library(dplyr)就像把书从书架上取下来:每次开始 R 会话时都要做(实际上就是写在每个脚本的开头)。这里不需要引号,library()比较特殊,可以直接接受不带引号的名字(如果你想保持一致,library("dplyr")也可以)。
两种报错会告诉你漏了哪一步。library() 报出 Error: there is no package called 'dplyr',说明这个包从来没装过。脚本运行到一半报 Error: could not find function "filter"(或 "%>%"),说明包已经装了,但这次会话没有加载它。把所有 library() 调用都放在脚本最顶部,而不是散落在中间,第二种错误在第一秒就会暴露出来,顺便也列出了这个脚本依赖哪些包。安装 tidyverse 也是一样:install.packages("tidyverse") 装一次,每次会话 library(tidyverse),一行就能加载 dplyr、ggplot2 和其余核心包。
你不应该把 install.packages() 留在需要反复运行或要分享给别人的脚本里:它每次运行都会重新下载,还可能让运行脚本的人措手不及。安装是在控制台里做的事,加载才是脚本里做的事。
require() 和 pkg::fun()
require() 看起来像是 library() 的同义词,很多人也确实把它当同义词用,这是一个常见的误用。区别在于包不存在时会发生什么:library() 报错并停止;require() 打印一条警告,返回 FALSE,然后让脚本继续运行,结果往往是二十行之后报出一个让人摸不着头脑的 "could not find function",而不是直接告诉你 "no package called"。加载依赖时请用 library():在脚本开头就明确地失败,是一个优点。require() 只在条件判断里才有用武之地,因为这时你要的正是它的返回值:
if (!require(praise)) {
install.packages("praise")
library(praise)
}
还有一种完全不加载包也能用它的方式::: 运算符通过完整地址调用某个函数,即 package::function()。包必须已经安装,但不会附加任何东西到你的会话中:
(stats 本来就会自动加载,所以直接写 sd() 也能用,但对任何已安装的包,语法都是一样的。):: 在两种场景下特别好用:只调用一次、不值得写一整行 library() 的时候;以及两个已加载的包导出了同名函数、需要区分的时候,dplyr::filter() 和 stats::filter() 就是经典的冲突。
保持包为最新版本
包的更新和 R 本身是独立的,所以更新要靠你自己:
update.packages() # offers to update everything outdated
update.packages(ask = FALSE) # same, without prompting per package
有一条不太显眼的规则:包是针对 R 的某个 major.minor 版本构建的。当你升级 R 本身时(比如从 4.3 升到 4.4,参见安装 R),旧的包库通常不会被带过去,解决办法很简单:在新版本下重新安装你用到的包。花十分钟跑一遍 install.packages(),不是什么大事,但第一次遇到时,看到脚本在新装的 R 上报出一大串 "no package called" 错误,很多人都会吓一跳。
查看你装了哪些包
有三个函数可以回答“装了什么、装在哪里”:
installed.packages()[, "Version"] # every installed package with its version
sessionInfo() # R version + what THIS session has loaded
.libPaths() # the folders where packages are installed
installed.packages() 返回一个矩阵,每个包占一行,你通常需要的是 Version 这一列。sessionInfo() 是保证可复现的工具:把它的输出贴到 bug 报告里,读者就能知道你的 R 版本、操作系统,以及每个已加载包的确切版本。.libPaths() 显示 R 搜索包的库文件夹;知道有这个函数,“那个包到底装到哪里去了?”就不再神秘,也能明白为什么在共用的电脑上有时需要管理员权限。
值得了解的包
今天你还用不到它们,但以后会经常遇到。知道每个包是做什么用的,能帮你读懂别人的代码:
- dplyr:数据处理的动词,
filter、mutate、group_by、summarize。 - ggplot2:标准的绘图包,你在网上看到的 R 图形大多是用 ggplot2 画的。
- tidyr:在宽格式和长格式之间转换数据(
pivot_longer、pivot_wider)。 - readr / readxl:分别用于快速读取 CSV 和读取 Excel 文件。
- lubridate:让日期的行为符合你的预期。
- stringr:风格统一的字符串处理。
- data.table:另一套高性能的数据框生态,和 tidyverse 是不同的写法,处理大数据时很受欢迎。
- shiny:完全用 R 编写交互式网页应用。
前六个是 tidyverse 的核心,用 install.packages("tidyverse") 会一起装好。你没有义务用其中任何一个(基础 R 全都能做到),但现代 R 代码大多都生活在这个生态里。
要点回顾
- CRAN 托管着约 20,000 个经过审核的包;Bioconductor 和 GitHub 覆盖其余部分。
install.packages("name")每台电脑一次(必须加引号);library(name)每次会话一次,写在脚本顶部。library()会明确地失败,这是好事;require()返回FALSE,只适合用在条件判断里。pkg::fun()可以在不附加整个包的情况下使用其中一个函数,还能解决名字冲突。update.packages()让包保持最新;R 的大版本升级意味着要重新安装包。sessionInfo()能告诉别人(或将来的你)你的代码到底是在什么环境下运行的。
下一篇:工作目录,也就是 R 在哪里查找文件,以及为什么读取数据失败时首先要检查它。
常见问题
R 中怎么安装包?
运行 install.packages("name"),包名要放在引号里,例如 install.packages("dplyr")。R 会从 CRAN 下载并安装到你的电脑上。每台电脑只需要装一次,之后在每次会话中用 library(dplyr) 加载即可。
install.packages() 和 library() 有什么区别?
install.packages("dplyr") 把包下载到你的电脑上,每台电脑做一次。library(dplyr) 把已经安装好的包加载到当前会话中,每次会话做一次,通常写在每个脚本的开头。只安装不加载,你什么也用不了;没安装就加载,会报错 "there is no package called 'dplyr'"。
R 中 library() 和 require() 有什么区别?
两者都能加载包,但加载失败时,library() 会报错并停止,而 require() 只给出警告并返回 FALSE。所以脚本里应该用 library(),尽早、明确地失败;require() 只在条件判断里有用,比如 if (!require(pkg)) install.packages(pkg)。