📜  R调试

📅  最后修改于: 2021-01-08 09:48:43             🧑  作者: Mango

什么是R Debug?

在计算机编程中,调试是一个多步骤的过程,其中涉及识别问题,找出问题的根源,然后解决问题或确定解决问题的方法。调试的最后一步是测试改进或变通方法,并确保其有效。

由于某些逻辑错误(称为“错误”),语法上正确的程序可能会给我们错误的结果。万一发生此类错误,那么我们需要找出发生这些错误的原因和位置,以便我们进行修复。识别和修复错误的过程称为“调试”

调试的基本原理

R程序员发现他们花在调试程序上的时间比实际编写或编码它的时间更多。这使调试技能的价值降低。在R中,调试有多种原理,可帮助程序员将时间花在编写和编码上,而不是调试上。这些原则如下:

1.调试的精髓

修复错误是一个确认过程。它逐渐证实,我们认为有关代码的许多方面实际上是真实的。当发现一个这样的假设是错误的时,我们找到了错误位置的线索。

例如

a <- b^2 + 3*c(z, 2)
x<- 28
if (x+q> 0) 
t<- 1 
else 
     u<- -10

2.从小处着手

至少在R调试过程开始时,坚持使用小的简单测试用例。使用大数据对象可能会很难考虑问题。当然,我们最终应该在大型,复杂的情况下测试我们的代码,但从小规模开始。

3.模块化调试

我们应该以自顶向下的方式进行调试。假设我们具有函数f()的调试状态,并且它具有下一行。

例如

Y <- g (x, 8)

目前,对调试说不(g)。执行该行,看看g()是否返回我们期望的值。如果发生这种情况,我们只需通过g()避免单步耗时的过程。如果g()返回的值不正确,则现在是时候调用debug(g)了。

4.防错

如果代码的某个部分中变量z应该为正,那么我们可以插入以下行以获得更好的性能:

Stopifnot(z> 0)

当代码中有错误(例如z的值等于-3)时,将调用Stopifnot()函数,并在此处显示错误消息:

错误:x> 0不是TRUE

职能

在R中,出于调试目的,有许多功能可用。这些功能在消除代码中的错误中起着重要的作用。 R提供以下调试功能:

1)traceback()

如果我们的代码已经崩溃,并且我们想知道进攻线在哪里,请尝试使用traceback()。这将(有时)在问题代码中显示位置。当R函数失败时,屏幕上会打印一个错误。错误发生后,我们可以立即调用traceback()来查看错误发生在哪个函数上。 traceback()函数打印出发生错误之前调用的函数列表。功能以相反的顺序打印。

让我们看一个示例,以了解如何使用traceback()函数

f <- function(a){
    x <- a-ql(a)
    x
}
ql<- function(b){
    r <- b*mn(b)
    r
}
mn<- function(p){
    r <- log(p)
    if(r<10)
        r^2
    else
        r^3
}
f(-2)

当我们运行上面的代码时,它将生成以下输出:

找到以下错误后,我们调用traceback()函数,并在运行时显示以下输出:

traceback()

2)debug()

在R中,debug()函数允许用户逐步执行一个函数。在任何时候,我们都可以print变量的值或在函数绘制结果图。在调试时,我们可以键入“ c”继续到当前代码块的末尾。 Traceback()不会告诉我们函数错误发生在哪里。要知道导致错误的行,我们必须使用debug()逐步执行该函数。

让我们看一个示例,以了解如何在R中使用调试函数。

func<- function(a,value){
subt<- value-a
squar<- subt^2
collect <- sum(squar)
collect
}
set.seed(100)
value <- rnorm(100)
func(1,value)
debug(func)
func(1,value)

输出量

3)浏览器()

直到用户允许它继续浏览器()函数停止的函数的执行。如果我们不想逐行逐步执行完整的代码,但是希望在特定时刻停止它,以便我们检查发生了什么,这很有用。

在函数的browser()中插入一个调用会在调用browser()的位置暂停该函数的执行。它与使用debug()相同,除了我们可以控制执行在何处暂停。

让我们看一个示例,以了解如何在R中使用browser()函数。

a<-function(b) {
  browser() ## a break point inserted here
  c<-log(b)
  if(c<10)
    c^2
  else
    c^3
}
a(-1)

输出量

4)trace()

trace()函数调用允许用户将一些代码插入到函数。对于初次使用的用户,R debug函数trace()的语法有些尴尬。使用debug()可能更好。

让我们看一个示例,以了解如何在R中使用browser()函数。

f <- function(a){
    x <- a-ql(a)
    x
}
ql<- function(b){
    r <- b*mn(b)
    r
}
mn<- function(p){
    r <- log(p)
    if(r<10)
        r^2
    else
        r^3
}
as.list(body(mn))
trace("mn",quote(if(is.nan(r)){browser()}),at=3,print=FALSE)
f(1)
f(-1)

输出量

5)恢复()

当我们执行函数调试时,restore()允许我们检查上级函数的变量。

通过在选择中键入数字,我们将导航到调用堆栈上的函数并部署在浏览器环境中。

recovery()函数用作错误处理程序,可使用options()进行设置(例如,采用(错误=检索))。

当函数引发错误时,执行将在失败时停止。我们可以浏览函数调用并检查环境以找到问题的根源。

f <- function(a){
    x <- a-ql(a)
    x
}
ql<- function(b){
    r <- b*mn(b)
    r
}
mn<- function(p){
    r <- log(p)
    if(r<10)
        r^2
    else
        r^3
}
as.list(body(mn))
trace("mn",quote(if(is.nan(r)){recover()}),at=3,print=FALSE)
f(-1)

输出量

调试已安装的软件包

安装的R软件包可能会导致错误。解决问题的几种方法如下:

  • 设置选项(错误=恢复),然后使用n逐行代码进行处理。
  • 在复杂情况下,我们应该拥有函数代码的副本。在R中,函数输入用于print可以复制到文本编辑器中的函数代码。我们可以通过将其加载到全局工作区中,然后执行调试来对其进行编辑。
  • 如果我们的问题没有解决,那么我们必须下载源代码。我们还可以使用devtools软件包以及install()和load_all()函数来使我们的过程更快。

错误处理和恢复

异常或错误处理是对代码奇数事件的响应过程,该事件会中断代码流。通常,异常处理程序的作用域以try开头,以catch结束。 R提供了try()和trycatch()函数。

try()函数是trycatch()的包装函数,该函数将打印错误,然后继续执行。另一方面,trycatch()使我们可以控制错误函数,并且可以选择继续执行该函数。