确保R环境中的重现性

geo*_*try 26 r

我在计算生物学实验室工作,在那里我们有几个人从事多个项目,主要是在R(这是我关心的这篇文章).在过去,人们只需为每个项目开发代码,这些代码可能涉及也可能不涉及从先前项目复制的样板代码.多年来我推动的一件事就是为这个混乱带来一些集中式结构,并让人们识别出常见的模式,这样我们就可以将这些重复/共同的代码块转换成包,因为人们可能会认为这是很多原因.一件好事.所以现在我们的人们在他们的项目特定脚本中使用了集中的包/例程.

这里有一个问题.我们拥有权力的授权,即每个项目的每个脚本都需要尽可能100%可重复(这包括我们可以直接访问的所有代码的100%,包括我们的包).也就是说,如果我在包条中使用参数A调用函数foo来获取结果X,那么4年后我应该得到完全相同的结果.(由于错误导致的错误输出在这里除外)

可重复性的主题现在在各个圈内的R中出现,但通常似乎在过程的再现性(例如,晕影)方面进行讨论.这不是一回事 - 我今天可以运行一个小插图然后在6个月后使用更新的包运行相同的代码并获得截然不同的结果.

已经达成一致的解决方案(我不是其中的粉丝)是,如果需要在非向后兼容的更改中更改函数或包,则只需获取新名称.因此,如果我们需要从根本上改变函数foo(),它将被称为foo2(),如果需要彻底改变,它将被称为foo3().这可以确保调用foo()的任何脚本始终获得原始结果,同时允许事物在包存储库中前进.它确实有效,但我真的不喜欢这个 - 它在美学上看起来非常混乱,我担心随着时间的推移它会导致包裹bar,bar2,bar3,bar4 ...函数foo1,foo2,foo3等的大规模混乱.

问题是我没有提出一个更好的替代解决方案.一种可能性是注意软件包的版本号,R等,并确保加载它们,但这有多个问题 - 其中最重要的是它依赖于正确的软件包版本规则并且容易出错.此外,这种替代方案已被拒绝;)理想情况下,我们所拥有的是某种开发和释放的概念,因为大多数这些变化往往更早发生,然后平稳发生变化的频率更低.OTOH devel在这里真正意味着"实际上并不是在一个包中"(我们这样做),但很难确切地确定在什么时候运送东西是正确的.当你认为自己安全的那一刻,那就是你认识到的那一刻

所以考虑到所有这些,我很好奇是否有其他人处理过类似情况,以及他们如何解决问题.

编辑:只是为了清楚,通过非向后兼容,我不只是谈论API等,而是输出给定的一组输入.

Cho*_*ens 20

这确实是一个重要的考虑因素,我认为最终需要将几个不同的过程制度化.

  1. 版本控制(svn,git,bzr,cvs等)
  2. 单元测试

我的第一反应是你需要将某种代码管理系统制度化.这将使它更容易,因为旧版本的foo()仍然可用,如果你真的想要它.根据您所说的,听起来您需要打包常用功能并制定某种发布计划.需要向后兼容的脚本必须包含软件包名称和发布信息.通过这种方式,可以始终像编写脚本时那样获得foo().你还应该确保人们只在他们的工作中使用官方发布版本,否则这可能会变得非常痛苦.

我同意,有一个foo的集合:foo99注定要失败.但至少它将是一个光荣迷茫的失败.除了美学,它将驱动你所有的疯狂.如果foo2()是foo()的改进(更准确,更快等),那么它应该被称为foo()并根据您公司范围的发布计划发布使用.如果它做了不同的事情,它就不再是foo()了.它可能是fooo()或superFoo()或fooMe(),但它不是foo().

最后,您需要开始测试您的功能.(单元测试)对于发布并可供其他人使用的每个功能,您应该有一个明确定义的测试套件.除非有人修复了foo()中的错误,否则结果应该保持不变.如果有人修复了错误,那么结果应该更准确,并且在大多数情况下可能更合适.如果确实需要重现旧的,不正确的结果,可以从版本控制系统中挖掘出旧版本的foo().通过严格的单元测试,您将知道foo的结果是否/何时发生了变化.这些知识应该有助于最小化您需要的foo()函数的数量.每次有人调整某些内容时,您可以测试新版本以查看结果是否符合预期,而不是创建版本.但是,这很棘手,因为您必须确保您的测试涵盖了该功能可能会看到的任何内容,包括奇怪的边缘情况.在研究环境中,我认为这可能成为一种挑战.


kmm*_*kmm 8

我不确定是否将它与R集成,但苏门答腊可能值得研究.它似乎允许您跟踪代码和结果.因此,如果您需要从4年前重新运行该模拟,那么代码应该存在.


Jor*_*eys 5

那么,问问自己,你会用其他任何语言做到这一点.除了好书记我真的没什么可怕的:

  • 记录所涉及的所有软件的版本号
  • 将代码放在易于管理的块中,比如在包中.
  • 确保所有涉及的软件/软件包在5年内仍然可用.

R可以很容易地移植,包括所有已安装的包.将可移植版本的R与所使用的软件包,代码 CD-ROM上的数据一起保存用于每次分析,并且您确定可以随时重现.好的,你错过了操作系统,但不能全部拥有它们.在任何情况下,如果操作系统的重要性足以使分析无法重现,那么很可能是您的分析问题.您不想告诉任何人您的结果取决于您使用的Windows版本,对吗?

PS:请进入人们的头脑,他们永远不应该在他们的生活中复制粘贴代码.他们应该将它包装在函数中并使用它们.更容易,更容易出错.我的意思是,复制之间有什么区别

x <- read.table("sometable")
y <- ColSums(x)/4.3
Run Code Online (Sandbox Code Playgroud)

并调整值或键入

myfun <- function(i,j){
  x <- read.table(i)
  y <- ColSums(x)/j
}
Run Code Online (Sandbox Code Playgroud)

为您和许多其他人节省了大量的复制粘贴麻烦.(怎么样,找不到物体?什么物体?)


Ric*_*ton 5

每当您想要以"永久"可再现的方式冻结代码时,例如,当您的论文发布时,最安全的方法是创建一个包含所有代码和数据以及所需软件的虚拟机运行它(包括操作系统).这里有华盛顿大学网站的一个例子.