哪些特定实用程序可以帮助R开发人员更有效地编码和调试?
我正在寻找一个R开发环境,并希望概述一些对我来说有用的工具,包括代码覆盖,调试,生成包文件和帮助文件等单元测试基础设施。 UML建模。
注意:请根据您对推荐工具的使用经验,根据原因和示例来证明您的答案。 不要只链接。
答案 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实例。
使用版本控制。我喜欢git
和github。同样,你使用哪个系统并不重要,但要掌握它!
我希望R拥有的东西:
答案 1 :(得分:46)
我记得以前曾经问过这个问题我的回答是一样的:Emacs。
Emacs可以
M-x shell
和/或M-x eshell
运行shell,具有带有dired模式的良好目录访问功能,具有用于远程访问的ssh模式<tongueInCheek>
不是Eclipse,不需要Java </tongueInCheek>
您当然可以将它与您喜欢的任何CRAN包结合使用:RUnit或testthat,不同的配置文件支持包,调试包,...
其他有用的工具:
R CMD check
真的是你的朋友,因为这是CRAN用来决定你是“进出”的东西;使用它并信任它tests/
目录可以通过保存待比较输出(来自之前的R CMD check
运行)来提供单元测试的简化版本,这很有用,但正确的单元测试更好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 包