专业的R开发人员应该拥有哪些核心包,为什么?

时间:2011-07-22 21:49:49

标签: unit-testing debugging r development-environment

哪些特定实用程序可以帮助R开发人员更有效地编码和调试?

我正在寻找一个R开发环境,并希望概述一些对我来说有用的工具,包括代码覆盖,调试,生成包文件和帮助文件等单元测试基础设施。 UML建模。

注意:请根据您对推荐工具的使用经验,根据原因和示例来证明您的答案。 不要只链接

相关

3 个答案:

答案 0 :(得分:49)

我写了太多的软件包,所以为了保持可管理性,我在基础架构软件包上花了很多时间:帮助我使代码更强大的软件包,帮助其他人更容易使用。其中包括:

  • roxygen2(与Manuel Eugster和Peter Danenberg一起),它允许您将文档保存在它所记录的函数旁边,这使得我更有可能保持它的最新状态。 roxygen2还有一些新功能,旨在最大限度地减少文档重复:模板(@template),参数继承(@inheritParams)和函数系列(@family)来命名少。

  • testthat自动测试我的代码。这变得越来越重要,因为我的代码编写时间越来越少:自动化测试记住了函数应该如何工作,即使我不这样做。

  • devtools自动执行许多常见的开发任务(正如Andrie所说)。 devtools的最终目标是让它像R CMD check一样在后台持续运行,并通知您实例出错。

  • profr,尤其是未发布的interactive explorer,让我很容易在代码中找到瓶颈。

  • helpr(与Barret Schloerke合作)即将推出http://had.co.nz/ggplot2,为R文档提供了一个优雅的html界面。

有用的R函数:

  • apropos:我总是忘记有用函数的名称,apropos帮助我找到它们,即使我只记得一个片段

在R之外:

  • 我使用textmate编辑R(和其他)文件,但我不认为它真的那么重要。选择一个并了解它的所有角落和缝隙。

  • 花一些时间学习命令行。从长远来看,您可以做的任何事情都可以使工作流程的任何部分自动化。从命令行运行R会导致一个自然过程,其中每个项目都有自己的R实例;我经常一次运行2-5个R实例。

  • 使用版本控制。我喜欢gitgithub。同样,你使用哪个系统并不重要,但要掌握它!

我希望R拥有的东西:

  • 代码覆盖率工具
  • 依赖管理框架,如rake或jake
  • 更好的内存分析工具
  • 用于描述数据帧(和其他数据源)的元数据标准
  • 用于描述和呈现各种输出格式的表的更好工具
  • 用于降价渲染的包

答案 1 :(得分:46)

我记得以前曾经问过这个问题我的回答是一样的:Emacs。

Emacs可以

  • 通过ESS做任何你想要做的事情,包括
    • 各种片段的代码执行(行,区域,函数,缓冲区......)
    • 检查工作空间,
    • 显示变量,
    • 多个R会话并在它们之间轻松切换
    • 转录模式,用于重新运行(部分)之前的会话
    • 访问帮助系统
    • 以及更多
  • 通过AucTex模式轻松处理乳胶,这有助于Sweave for R
  • 具有与R结合使用的其他编程语言的模式,无论是C / C ++,Python,shell,SQL,...还包括自​​动缩进和颜色突出显示
  • 可以使用sql- * mode
  • 访问数据库
  • 可以使用tramp模式远程工作:访问远程文件,就好像它们是本地的一样(使用ssh / scp)
  • 可以作为守护进程运行,使其成为有状态,这样您就可以重新连接到同一个Emacs会话,无论是在X11(或同等版本)下的工作站上,还是通过ssh(带或不带X11)或屏幕远程连接。
  • org-mode,与babel一起提供了强大的sweave替代方案,如所讨论in this paper discussing workflow apps for (social) scientists
  • 可以通过M-x shell和/或M-x eshell运行shell,具有带有dired模式的良好目录访问功能,具有用于远程访问的ssh模式
  • 通过特定模式轻松连接所有源代码存储库(例如psvn for svn)
  • 与R一样是跨平台的,因此您在所有相关操作系统上拥有类似的用户界面体验
  • 被广泛使用,广泛使用并且正在积极开发代码和扩展,请参阅emacswiki.org网站了解后者
  • <tongueInCheek>不是Eclipse,不需要Java </tongueInCheek>

您当然可以将它与您喜欢的任何CRAN包结合使用:RUnit或testthat,不同的配置文件支持包,调试包,...

其他有用的工具:

  • R CMD check真的是你的朋友,因为这是CRAN用来决定你是“进出”的东西;使用它并信任它
  • tests/目录可以通过保存待比较输出(来自之前的R CMD check运行)来提供单元测试的简化版本,这很有用,但正确的单元测试更好
  • 特别是对于带有目标代码的包,我更喜欢启动新的R会话,而littler使这很简单:r -lfoo -e'bar(1, "ab")'启动R会话,加载foo包并评估给定的表达式(这里是一个带有两个参数的函数bar())。这与R CMD INSTALL相结合,提供了一个完整的测试周期。

答案 2 :(得分:8)

了解和使用基本R调试工具的能力是学习快速调试R代码的关键第一步。如果您知道如何使用基本工具,则可以在任何地方调试代码,而无需添加附加软件包中提供的所有额外工具。

traceback()允许您查看导致错误的调用堆栈

foo <- function(x) {
    d <- bar(x)
    x[1]
}
bar <- function(x) {
    stopifnot(is.matrix(x))
    dim(x)
}
foo(1:10)
traceback()

的产率:

> foo(1:10)
Error: is.matrix(x) is not TRUE
> traceback()
4: stop(paste(ch, " is not ", if (length(r) > 1L) "all ", "TRUE", 
       sep = ""), call. = FALSE)
3: stopifnot(is.matrix(x))
2: bar(x)
1: foo(1:10)

因此我们可以清楚地看到错误发生在函数bar()中;我们缩小了寻找bug的范围。但是如果代码生成警告而不是错误呢?这可以通过warn选项将警告变为错误来处理:

options(warn = 2)

会将警告变为错误。然后,您可以使用traceback()跟踪它们。

与此相关联是让R从代码中的错误中恢复,以便您可以调试出错的地方。每当出现错误时,options(error = recover)都会将我们放入调试器框架中:

> options(error = recover)
> foo(1:10)
Error: is.matrix(x) is not TRUE

Enter a frame number, or 0 to exit   

1: foo(1:10)
2: bar(x)
3: stopifnot(is.matrix(x))

Selection: 2
Called from: bar(x)
Browse[1]> x
 [1]  1  2  3  4  5  6  7  8  9 10
Browse[1]> is.matrix(x)
[1] FALSE

你看我们可以进入调用堆栈的每一帧,看看函数是如何被调用的,参数是什么等等。在上面的例子中,我们看到bar()传递了一个向量而不是一个矩阵,因此错误。 options(error = NULL)将此行为重置为正常。

另一个关键函数是trace(),它允许您将调试调用插入现有函数。这样做的好处是,您可以告诉R从源中的特定行进行调试:

> x <- 1:10; y <- rnorm(10)
> trace(lm, tracer = browser, at = 10) ## debug from line 10 of the source
Tracing function "lm" in package "stats"
[1] "lm"
> lm(y ~ x)
Tracing lm(y ~ x) step 10 
Called from: eval(expr, envir, enclos)
Browse[1]> n ## must press n <return> to get the next line step
debug: mf <- eval(mf, parent.frame())
Browse[2]> 
debug: if (method == "model.frame") return(mf) else if (method != "qr") warning(gettextf("method = '%s' is not supported. Using 'qr'", 
    method), domain = NA)
Browse[2]> 
debug: if (method != "qr") warning(gettextf("method = '%s' is not supported. Using 'qr'", 
    method), domain = NA)
Browse[2]> 
debug: NULL
Browse[2]> Q
> untrace(lm)
Untracing function "lm" in package "stats"

这允许您在代码中的正确位置插入调试调用,而无需单步执行前面的函数调用。

如果要在执行时逐步执行函数,则debug(foo)将打开函数foo()的调试器,而undebug(foo)将关闭调试器。

关于这些选项的一个关键点是我不需要修改/编辑任何源代码来插入调试调用等。我可以尝试一下,直接从发生错误的会话中查看问题所在。

有关R中的不同调试,请参阅Mark Bravington在CRAN上的 debug