我最近开始研究 Makefile 来跟踪我的研究项目中的脚本。为了真正了解发生了什么,我想更好地了解
R CMD BATCH
生成的 .Rout 文件的内容。
Christopher Gandrad 在他的书《使用 R 和 RStudio 进行可重复研究》中使用 Makefile。示例项目 (https://github.com/christophergandrud/rep-res-book-v3-examples/tree/master/data) 只有三个 .R 文件:其中两个下载并清理数据,第三个合并两个数据集。它们由 Makefile 的以下几行调用:
# Key variables to define
RDIR = .
# Run the RSOURCE files
$(RDIR)/%.Rout: $(RDIR)/%.R
R CMD BATCH $<
前两个文件都没有输出数据;合并脚本也不会显式导入数据 - 它只是使用
在前两个脚本中创建的对象。那么脚本之间的数据是如何保存的呢? 对我来说,批处理执行似乎发生在同一个 R 环境中,保留了对象和加载的包。事实真的如此吗?是将对象从一个脚本传输到另一个脚本的 .Rout 文件,还是批处理执行本身的一个属性?
如果脚本之间确实保留了工作环境,那么如果不同包中存在具有相同名称的对象或具有相同名称的函数,我会发现很多潜在的问题。此设置的另一个问题似乎是 Makefile 无法传播下游前两个文件中的更改,因为合并脚本没有明确的输入/先决条件。
我很乐意了解我的直觉是否正确,以及是否有更好的方法在 Makefile 中执行 R 文件。
R CMD BATCH
会将您的工作区保存到隐藏的
.Rdata
文件中,除非您选择--no-save
。这就是为什么它并不是运行 R 脚本的推荐方法。推荐的方式是使用Rscript
,默认不保存。如果您想要的话,您必须显式编写代码来保存。这与 Rout
文件不同,后者应该仅包含脚本中运行的命令的输出。在这种情况下,执行不会发生在完全相同的环境中。 R 仍然被调用三次,但是该环境在每次运行之间被序列化并重新加载。
您是对的,默认情况下保存和重新加载工作区可能会出现很多问题。这就是为什么大多数人建议您不要这样做。但出于这个原因,作者只是认为这让他们的工作流程变得更容易,所以他们使用了它。不过,一般来说,最好对输入和输出文件更加明确。