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

Mar*_*ark 46 debugging unit-testing development-environment r

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

我正在寻求建立一个R开发环境,并希望概述一些对我来说有用的工具,包括代码覆盖,调试,包文件和帮助文件的生成以及可能的UML建模.

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

有关

had*_*ley 50

我写了太多的软件包,所以为了保持可管理性,我在基础架构软件包上投入了大量时间:帮助我使代码更加健壮并帮助其他人更轻松地使用的软件包.这些包括:

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

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

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

  • profr,特别是未发布的交互式浏览器,使我很容易在我的代码中找到瓶颈.

  • 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
  • 更好的内存分析工具
  • 用于描述数据帧(和其他数据源)的元数据标准
  • 更好的工具,用于以各种输出格式描述和呈现表格
  • 用于降价渲染的包

  • 命令行位不能被夸大.通过基本的unix CLI知识,可以将其生产力提高一个数量级. (3认同)
  • @Krishna - 我正在考虑更像[qnch]的外部格式(http://eagereyes.org/blog/2009/qnch-data-description-language-for-tabular-data.html). (2认同)
  • 另外:我在关闭之后标记了要进行更多审核的问题(在我看来,这是一个低/负效用社区 - 不利行动).这不能成为社区维基吗?意图是肯定的:虽然标记可能看起来是负面的 - 我的意图不是影响OP,而是结束. (2认同)

Dir*_*tel 46

我记得以前曾经问过,我的答案仍然是一样的:Emacs.

Emacs可以

  • 感谢ESS,你可以做任何你想做的事情,包括
    • 代码执行各种片段(行,区域,函数,缓冲区......)
    • 检查工作空间,
    • 显示变量,
    • 多个R会话,并在它们之间轻松切换
    • 用于重新运行(部分)先前会话的记录模式
    • 访问帮助系统
    • 以及更多
  • 通过AucTex模式轻松处理乳胶,这有助于Sweave for R
  • 有任何其他编程语言与R结合的模式,无论是C/C++,Python,shell,SQL,......涵盖自动缩进和颜色突出显示
  • 可以使用sql-*模式访问数据库
  • 可以使用tramp模式远程工作:访问远程文件,就好像它们是本地的一样(使用ssh/scp)
  • 可以作为守护进程运行,使其成为有状态,这样您就可以重新连接到同一个Emacs会话,无论是在X11(或等效)下的工作站上,还是通过ssh(带或不带X11)或屏幕远程连接.
  • org-mode,它与babel一起提供了强大的sweave替代方案,如本文讨论的讨论(社会)科学家的工作流应用程序
  • 可以通过M-x shell和/或M-x eshell具有带有直接模式的良好目录访问功能运行shell ,具有用于远程访问的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,提供了完整的测试周期.


Rei*_*son 9

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

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

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

收益率:

> 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)
Run Code Online (Sandbox Code Playgroud)

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

options(warn = 2)
Run Code Online (Sandbox Code Playgroud)

会将警告变成错误.然后,您可以使用它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
Run Code Online (Sandbox Code Playgroud)

你看,我们可以进入调用堆栈的每一帧,看看函数是如何被调用的,参数是什么等等.在上面的例子中,我们看到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"
Run Code Online (Sandbox Code Playgroud)

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

如果要在执行时逐步执行debug(foo)函数foo(),undebug(foo)则会打开调试器以获取函数,同时将关闭调试器.

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

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