【问题标题】:Strategies for repeating large chunk of analysis重复大量分析的策略
【发布时间】:2011-06-22 08:47:38
【问题描述】:

我发现自己已经完成了大量分析,现在需要在输入假设略有不同的情况下重复分析。

在这种情况下,分析涉及聚类分析、绘制多个图表以及导出聚类 ID 和其他感兴趣的变量。关键是它是一个广泛的分析,只需要重复和比较两次。

我考虑过:

  • 创建函数。这并不理想,因为我必须修改我的代码才能知道我是在函数还是父环境中进行评估。这种额外的努力似乎过度,使调试变得更加困难,并且可能会带来副作用。
  • 将其包装在一个 for 循环中。同样,不理想,因为那时我必须创建索引变量,这也会引入副作用。
  • 创建一些前导代码,将分析包装在一个单独的文件中并source 它。这可行,但看起来非常丑陋且不理想。

分析的目的是完成一组对象(在列表中或在单独的输出文件中),我可以进一步分析它们的差异。

处理这类问题的好策略是什么?

【问题讨论】:

    标签: r


    【解决方案1】:

    使代码可重用需要一些时间和精力,并且像您提到自己一样面临一些额外的挑战。

    是否投资的问题可能是信息学中的关键问题(如果不是在许多其他领域):我是要编写一个脚本以类似的方式重命名 50 个文件,还是继续手动重命名它们。

    我相信,答案是高度个人化的,即便如此,也因情况而异。如果你对编程很容易,你可能会更早地决定走复用路线,因为你的努力会相对较低(即使那样,程序员通常也喜欢学习新技巧,所以这是一种隐藏的,往往适得其反的动机)。

    也就是说,在您的特定情况下:我会选择采购选项:由于您计划仅将代码重用 2 次,因此可能会浪费更大的努力(您表示分析相当广泛)。那么,如果它不是一个优雅的解决方案呢?没有人会看到你这样做,每个人都会对快速的结果感到满意。

    如果结果在一年左右后重复使用率高于预期,那么您仍然可以进行投资。到那时,您还将拥有(至少)三个案例,您可以将代码的重写和时髦的可重用版本的结果与当前结果进行比较。

    如果/当我事先知道我要重用代码时,我会在开发时尽量记住这一点。无论哪种方式,我几乎从不编写不在函数中的代码(好吧,除了 SO 和其他开箱即用分析的两行代码):我发现这让我更容易构建我的想法。

    【讨论】:

    • +1 因为你只会再做两次。答案还取决于您每次通过分析将有多少变化——只需几个参数、输入数据、?我发现在 (1) 提取关键参数并在代码顶部定义它们 [或将它们放在单独的文件中并 source()ing 分析正文] 和 (2) 包装函数中的代码主体。我不清楚您的父环境与功能环境的区别是什么。
    • +1 这几乎就是我最后所做的。我将所有为每次运行更改的参数包装到一个列表中。然后创建不同的列表(具有相同的结构),其中包含每次运行的输入值。对于每次迭代,我复制了必要的列表并将结果变量保存到输出列表中。换句话说,将一些代码包装成序言和清理,并完成工作。有用。丑了也没关系……
    【解决方案2】:

    如果可能,请在外部参数文件中设置不同组/运行/实验之间的参数。然后,您可以获取代码、调用函数,甚至使用包,但操作由一小组外部定义的参数决定。

    例如,JSON 非常适用于此,RJSONIOrjson 包允许您将文件加载到列表中。假设您将其加载到名为 parametersNN.json 的列表中。一个例子如下:

    {
     "Version": "20110701a",
     "Initialization":
     {
       "indices": [1,2,3,4,5,6,7,8,9,10],
       "step_size": 0.05
     },
     "Stopping":
     {
       "tolerance": 0.01,
       "iterations": 100
     }
    }
    

    将其保存为“parameters01.json”并加载为:

    library(RJSONIO)
    Params <- fromJSON("parameters.json")
    

    然后你就开始跑步了。 (注意:我喜欢在我的参数文件中使用唯一版本#s,以便我以后可以识别该集合,如果我正在查看 R 中的“参数”列表。)只需调用您的脚本并指向参数文件,例如:

    Rscript --vanilla MyScript.R parameters01.json
    

    然后,在程序中,从commandArgs() 函数中识别参数文件。

    稍后,您可以将代码分解为函数和包,但这可能是让 vanilla 脚本在短期内通用化的最简单方法,从长远来看,这是一个很好的做法,因为代码应该与运行/数据集/实验相关参数的规范。

    编辑:更准确地说,我什至会在 JSON 中指定输入和输出目录或文件(或命名模式/前缀)。这使得一组参数如何导致一个特定的输出集变得非常清楚。两者之间的所有内容都只是使用给定参数化运行的代码,但代码应该不会有太大变化,不是吗?


    更新: 三个月,数千次运行,比我之前的回答更明智,我会说 JSON 中参数的外部存储对于 1-1000 次不同的运行很有用。当参数或配置数以千计以上时,最好切换到使用数据库进行配置管理。每个配置都可能源自 JSON(或 XML),但能够处理不同的参数布局需要更大规模的解决方案,SQLite 之类的数据库(通过RSQLite)是一个很好的解决方案。

    我意识到这个答案对于最初的问题来说太过分了——如何只重复几次工作,改变一些参数,但是在正在进行的研究中扩大到数百或数千个参数变化时,需要更广泛的工具. :)

    【讨论】:

    • 这对我来说是一个非常有用的答案。我什至没有一路走到JSON,只是在配置目录中使用了一个小的.R 脚本。 Grid Engine 设置了一个包含作业名称的环境变量,因此我可以读取它并让它为该运行提取同名的配置文件。很适合我的需要;听起来你的更充实!
    • @AriB.Friedman 很高兴为您提供帮助! DB 方法似乎适用于成千上万的人。如果不出意外,您可以将参数设置视为类似于实验设计 - 将设计参数存储在数据库中是可扩展的,最终我们确实想知道为什么不同的运行会产生不同的结果。
    【解决方案3】:

    在这些情况下,我喜欢结合使用一个小 shell 脚本、一个 pdf 裁剪程序和 Sweave。这会给你带来很好的报告,并鼓励你去寻找。通常我会处理多个文件,几乎就像创建一个包一样(至少我认为是这样的:)。我有一个用于数据处理的单独文件和用于不同类型分析的单独文件,例如 descriptiveStats.R、regressions.R。

    顺便说一句,这是我的小 shell 脚本,

     #!/bin/sh
     R CMD Sweave docSweave.Rnw
     for file in `ls pdfs`;
     do pdfcrop  pdfs/"$file" pdfs/"$file"
     done
     pdflatex docSweave.tex
     open docSweave.pdf 
    

    Sweave 文件通常会在需要时获取上述 R 文件。我不确定这是否是你要找的,但这是我迄今为止的策略。我至少相信创建透明、可重复的报告有助于遵循至少 A 策略。

    【讨论】:

    • +1 我将不得不更多地探索 shell 脚本 - 我倾向于不将它们与 R 一起使用。这似乎等同于,或者至少类似于使用 source
    • 这完全取决于操作系统。我还不确定 python、shell 脚本或苹果脚本是否最适合我的需求,但据我判断,使用 R 的 shell 脚本似乎真的值得一看,尤其是对于自动报告。
    【解决方案4】:

    您的第三个选项还不错。我在很多情况下都会这样做。您可以通过将前置示例代码的结果放入环境中来构建更多结构,并附加您想要用于进一步分析的那个。 一个例子:

        setup1 <- local({
              x <- rnorm(50, mean=2.0)
              y <- rnorm(50, mean=1.0)
              environment()
              # ...
            })
    
        setup2 <- local({
              x <- rnorm(50, mean=1.8)
              y <- rnorm(50, mean=1.5)
              environment()
              # ...
            })
    

    attach(setup1) 并运行/获取您的分析代码

    plot(x, y)
    t.test(x, y, paired = T, var.equal = T)
    ...
    

    完成后,detach(setup1) 并附上第二个。

    现在,至少您可以轻松地在设置之间切换。帮了我几次。

    【讨论】:

    • +1 这种方法真的很有趣。我通常尽量避免使用attach,但我喜欢创建环境来解决这个问题的想法。我将进一步探索。
    • 我也喜欢这个,就像安德烈提到的那样,在使用“附加”时要小心谨慎。这样做的好处是它比参数列表更通用,并且可以包含计算。
    【解决方案5】:

    我倾向于将此类结果推送到全局列表中。 我使用 Common Lisp,但 R 并没有那么不同。

    【讨论】:

    • +1 是的,这就是我最后所做的。创建一个需要更改的变量列表和另一个包含结果的列表。然后切换局部变量进出列表。
    【解决方案6】:

    在这里对你来说太晚了,但我经常使用 Sweave,而且很可能我从一开始就使用了 Sweave 文件(例如,如果我知道最终产品需要是某种报告)。

    对于第二次和第三次重复部分分析,有两个选项:

    • 如果结果相当“独立”(即应该生成 3 个报告,比较意味着报告被并排检查),并且更改的输入以新数据文件的形式出现目录和 Sweave 文件的副本,然后我创建单独的报告(类似于源,但 Sweave 比普通源更自然)。

    • 如果我宁愿需要在一个 Sweave 文件中再次执行完全相同的操作一次或两次,我会考虑重用代码块。这类似于丑陋的 for 循环。

      原因是结果当然会放在一起进行比较,这将是报告的最后一部分。

    • 1234563函数(即我实际上是在编辑器窗口中编写函数,但在编写函数时直接在工作区中评估行)。

    鉴于您处于所描述的情况,我同意尼克的观点 - source 没有任何问题,因为您已经将它作为脚本,所以其他一切都意味着更多的努力。

    【讨论】:

      【解决方案7】:

      我无法对 Iterator 的答案发表评论,所以我必须在此处发布。我真的很喜欢他的回答,所以我制作了一个简短的脚本来创建参数并将它们导出到外部 JSON 文件。我希望有人觉得这很有用:https://github.com/kiribatu/Kiribatu-R-Toolkit/blob/master/docs/parameter_configuration.md

      【讨论】:

        猜你喜欢
        • 2011-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-09-29
        • 2011-03-26
        • 2018-01-31
        • 1970-01-01
        相关资源
        最近更新 更多