跨 R 项目传输 objects 的最佳实践是什么?

What is the best practice for transferring objects across R projects?

我想在另一个 git-versioned R 项目中使用在一个 git-versioned R 项目中生成的 R objects(例如,清理数据)。

具体来说,我有多个 git-versioned R 项目(持有 drake 计划)为我的论文实验做各种事情(例如,生成材料、导入和清理数据、生成 reports/articles).

experiment-specific 个项目理想情况下应该是:

  1. 可连接 - 这样我就可以将我在这些项目中生成的 objects(主要是数据和材料)导入到另一个生成我的论文报告的 git-versioned R 项目中。
  2. Self-contained - 这样我就可以在其他 non-thesis 项目(例如演示文稿、报告和期刊手稿)中使用它们。在共享此类项目时,我希望不需要共享一个单一的论文项目。
  3. 版本化 - 以便它们在不同项目中的使用可以独立(例如,如果我在提交论文后对手稿的数据清理进行了更改,我仍然希望论文能够像最初编译的那样可重现) .

目前我可以看到三种方法:

  1. Re-create数据清理过程
    • 但是:这涉及 copy/paste,我想避免这种情况,尤其是当上游发生变化时。
  2. 通过更改工作目录访问相关的scripts/functions
    • 但是:即使我使用 here 似乎这会引入较差的再现性。
  3. 将源项目打包并制作 objects 我想“导出”到导出的数据(根据 the data section of Hadley's R packages guide

还有其他方法吗?

编辑: 我尝试了 of using a single drake plan, which worked well for a while, until (similar to ) 我最终得到了太多 sub-projects(例如,会议报告和手稿)依赖于相同的 objects。因此,我在上面添加了一些澄清我的问题的意图。

我的第一个建议是使用单个 drake 计划来统一整个项目中需要共享数据的阶段。 drake 旨在以这种方式处理大量移动部件,并且在 drake 决定在下游重新运行什么时会更加无缝。但是,如果您确实需要在不同 sub-projects 中共享数据的不同计划,您可以在一个计划中将每个共享数据集作为 file_out() 文件进行跟踪,并在另一个计划中使用 file_in() 对其进行跟踪。

upstream_plan <- drake_plan(
  export_file = write_csv(dataset, file_out("exported_data/dataset.csv"))
)
downstream_plan <- drake_plan(
  dataset = read_csv(file_in("../upstream_project/exported_data/dataset.csv"))
)

您从根本上误解了 Miles McBain 的批评。他并不是说你不应该编写可重用的代码,也不是说你不应该使用包。他说你不应该为 一切 使用包。但是可重用代码(即您想要重用的代码)绝对属于包(或者更好,modules),然后可以在多个项目中使用。

话虽如此,首先,请注意 Will Landau 的建议。

其次,您可以使您的 RStudio 项目可配置,这样它们就可以根据配置中给定的路径加载数据。完成后,没有什么反对 hard-coding 配置文件中不同项目中数据的路径。

我也有类似情况。我有许多项目是从一个原始数据集衍生出来的。以前,当项目还很小的时候,我把所有的东西都放在一个版本控制的项目中。随着更多子项目的产生,我的 git 历史因并行处理项目而变得混乱,这变得一发不可收拾。这可能是因为我缺乏 git 的技能。我的文件夹结构如下所示:

project/.git  
project/main/  
project/sub-project_1/  
project/sub-project_2/  
project/sub-project_n/

我打算将每个项目放在自己的 git 分支中,但后来我无法同时访问它们。如果我必须对主数据集进行一些更改(例如,我可能没有清理某些部分),那么项目 1 可能会过时且无法正常工作。完成项目 1 后,我希望将其隔离和包含以实现可重复性。如果项目是分开的,这更容易实现。我不认为 drake/targets 计划可以解决这个问题?

我还简要地研究了将项目作为 git 子模块,但它似乎增加了太多的复杂性。同样,我的 git 无知可能会在这里闪耀。

我目前的解决方案是将主要数据作为 R 包,并将每个子项目作为单独的 git 版本文件夹(它们实际上也是包,但这不是必需的) .这样我就可以加载特定版本的数据(使用 renv 作为包版本)。

我的文件夹结构现在看起来像这样:

main/.git  
sub-project_1/.git  
sub-project_2/.git  
sub-project_n/.git

在每个子项目中,我调用 library(main) 加载清理后的数据。在每个子项目中,可以使用 drake/targets 计划。