PAYATHON 2026

如何将旧版本 R 中已安装的包快速迁移到新版本?

技术老齐

在 Windows 上,最快见效的调整是将 type = "source" 改为 type = "binary",并将 dependencies = TRUE 改为默认的 dependencies = NA。这样可以直接安装适用于当前 R 的预编译包,减少源码编译和额外依赖带来的耗时。

从 R 4.5.x 升级到 R 4.6.x 时,建议按旧包清单重新安装。跨越 major.minor 版本后,旧包可能与新 R 不兼容,R 官方 Windows FAQ 也明确建议不要直接复制旧包目录。R for Windows FAQ

为什么原来的安装方式很慢?

原代码中的两个参数增加了安装工作量:

  • type = "source" 强制从源码安装。包含 C、C++ 或 Fortran 代码的包需要编译,在 Windows 上通常还需要与当前 R 匹配的 Rtools。
  • dependencies = TRUE 会额外安装目标包的 Suggests 依赖,其中可能包含仅在运行示例、测试和 vignette 时才需要的包。日常使用通常保留默认值 NA 即可,它会处理必要依赖;源码安装时还包括 LinkingTo。install.packages() 官方文档

包数量接近 1500 时,这两项设置会明显增加安装量。具体耗时还取决于网络、硬件和二进制包是否齐全,无法保证在固定时间内完成。

如何处理“源码版本比二进制版本新”的提示?

这条提示说明仓库中的源码版本与二进制版本不同,不表示文件损坏。例如,题目中 crs 的二进制版本为 0.15-41,源码版本为 0.15-42;needs_compilation = TRUE 表示安装该源码版本需要编译。

只删除 type = "source",仍可能因当前设置而选择较新的源码版本。要明确使用二进制包,应指定:

install.packages(
  pkg_current$Package,
  repos = c(CRAN = "https://cloud.r-project.org"),
  type = "binary",
  dependencies = NA
)

即使源码版本更新,type = "binary" 也会选择适用于当前 R 的二进制版本。没有对应二进制包时,不会自动改为源码安装。二进制安装说明

第一步:在旧 R 中保存包清单

用基础 R 就能保存包名,无须加载 dplyr 或 tibble。以下代码会排除随 R 提供的 base 和 recommended 包,并去除重复名称:

# 在旧版本 R 中运行
ip <- installed.packages()

pkgs <- unique(ip[is.na(ip[, "Priority"]), "Package"])

saveRDS(pkgs, file = "packages.rds")

文件会保存在当前工作目录,可用 getwd() 查看位置。之后在新 R 中读取同一个文件即可。

如果已经有题目中的 packages.txt,可以继续使用,无须重新导出:

pkgs <- read.table(
  "C:/Users/Documents/packages.txt",
  header = TRUE,
  row.names = 1,
  stringsAsFactors = FALSE
)$Package

pkgs <- unique(pkgs)

第二步:在新 R 中筛选并安装 CRAN 二进制包

先确认启动的是新 R,包库路径也没有指向旧版本的个人包库:

R.version.string
.libPaths()

运行以下代码前,请将文件路径改为实际位置。如果已经从 TXT 文件中读出了 pkgs,跳过 readRDS() 这一行。

# 在新版本 R 中运行
pkgs <- readRDS("C:/Users/Documents/packages.rds")

repos <- c(CRAN = "https://cloud.r-project.org")

# 查询适用于当前 R 的 CRAN 二进制包
binary_db <- available.packages(
  repos = repos,
  type = "binary"
)

# 旧清单中可以通过二进制方式恢复的包
binary_pkgs <- intersect(pkgs, rownames(binary_db))

# 跳过新 R 中已经安装的包,便于中断后继续
todo <- setdiff(
  binary_pkgs,
  installed.packages()[, "Package"]
)

if (length(todo) > 0L) {
  install.packages(
    todo,
    repos = repos,
    type = "binary",
    dependencies = NA
  )
}

# 单独列出没有对应二进制包的名称
no_binary <- setdiff(pkgs, rownames(binary_db))
no_binary

available.packages() 默认按 R 版本、操作系统等条件筛选仓库中的包,因此得到的是当前环境可用的包列表。available.packages() 官方文档

这里按包名筛选,只能判断当前 CRAN 仓库中是否有可用的同名包。如果某个包原先从 GitHub 安装,而 CRAN 也有同名包,这段代码会安装 CRAN 版本,无法恢复 GitHub 上的特定提交或修改。

第三步:单独处理没有二进制版本的包

no_binary 中的包不一定都来自 GitHub,也可能在 CRAN 上只有源码版本,或当前版本不适用于新 R。可以进一步区分:

source_db <- available.packages(
  repos = repos,
  type = "source"
)

# 当前 CRAN 有适用源码版本,但没有对应二进制版本
source_only <- intersect(no_binary, rownames(source_db))

# 当前 CRAN 可用源码列表中也找不到
other_pkgs <- setdiff(no_binary, rownames(source_db))

source_only
other_pkgs

对于 source_only 中的包,可以等待二进制版本,也可以只选急需的包从源码安装。需要编译时,再配置相应的 Rtools。other_pkgs 中的包则需要逐个核对原安装来源、归档状态和版本要求。

仅保存包名无法恢复原来的包版本,也无法记录完整的 GitHub 仓库、分支或提交信息。这套方法适合恢复常用包集合;如果需要精确复现旧项目,还应保留原环境的版本和来源记录。

安装后还要检查什么?

先检查本轮要安装的包是否还有缺失:

remaining <- setdiff(
  binary_pkgs,
  installed.packages()[, "Package"]
)

remaining

remaining 为空,只能说明这些包已经安装。还需要加载常用包,并运行关键项目脚本,确认实际行为正常。

updateR() 的“corruption files”错误需要完整错误信息才能定位,仅凭这段描述无法判断原因。迁移包清单不依赖 updateR(),新 R 安装成功后,可以直接按上述步骤操作。

备注:内容仅供参考。