vlambda博客
学习文章列表

数据科学05 | R语言程序设计-调试工具与str函数

调试工具debugging tools

➢条件condition

用于提示运行函数过程中意外事件或错误的发生,编写函数时可以自行创造新的提示条件。

  • message:由message()产生,输出提示信息到Console控制台,不会阻止函数运行

  • warning:由warning()产生,运行过程出现潜在的问题,函数继续执行,完全执行后输出警告

  • error:由stop()产生,运行过程出现重大问题无法继续,强制终止运行

#warninglog(-1)[1] NaNWarning message:In log(-1) : 产生了NaNs#取一个负数的常用对数,返回NaN表示非数字 (Not a number) 
#errorprintmessage <- function(x) { if(x>0) print("x is greater than zero") else print("x is less than or equal to zero") invisible(x)}
printmessage(1)[1] "x is greater than zero"
printmessage(NA)Error in if (x > 0) print("x is greater than zero") else print("x is less than or equal to zero") : 需要TRUE/FALSE值的地方不可以用缺少值

➢调试函数时按以下流程考虑问题

1)实际输入函数的是什么?
2)预期结果是什么?
3)怎么调用函数?参数是什么?
4)实际结果和预期结果之间有何区别?
5)最初的预期是否正确?
6)能否重塑问题?(如设定随机数种子,重复产生问题的过程)

➢R中的调试工具  

  • traceback 函数:打印函数调用栈 (function call stack),说明一共调用了多少个函数,以及错误发生的位置

  • debug 函数:传递一个函数作为参数,可以标记这个函数,进入调试模式(debug mode)

    调试模式(debug mode):每当执行到这个函数时都会暂停执行,停在这个函数的第一行  

  • browser 函数:在代码的任何地方调用 browser(),函数会停止执行,能从那里开始逐行运行,找出出现错误的代码具体是哪一行

  • trace 函数:trace 函数允许在函数中插入调试代码,避免了编辑函数本身

  • recover 函数R默认在报错之后回到控制台,通过设置错误处理器 (error handler)可改变这种默认行为。recover() 是错误处理函数,函数遇到错误时R编译器停止执行,但不回到控制台,会停在函数出错的地方,输出函数调用栈。

lm(y~x) Error in eval(expr, envir, enclos) : object ’y’ not found
traceback()7: eval(expr, envir, enclos)6: eval(predvars, data, env)5: model.frame.default(formula = y ~ x, drop.unused.levels = TRUE)4: model.frame(formula = y ~ x, drop.unused.levels = TRUE)3: eval(expr, envir, enclos)2: eval(mf, parent.frame())1: lm(y~x)

出错在第7层函数,出错原因是它试图解析公式y~x,eval()在解析公式时无法找到 y 和 x 的实际值。

必须在错误发生后马上调用 traceback函数,traceback函数只能给出上一次执行的错误。

debug(lm) lm(y~x)debugging in: lm(y ~ x) debug: {  ret.x <- x ret.y <- y cl <- match.call()  mf <- match.call(expand.dots = FALSE) m <- match(c("formula", "data", "subset", "weights", "na.action",  "offset"), names(mf), 0L) mf <- mf[c(1L, m)] mf$drop.unused.levels <- TRUE mf[[1L]] <- quote(stats::model.frame) mf <- eval(mf, parent.frame()) ... if (!qr) z$qr <- NULL  z} Browse[2]> n debug: ret.x <- xBrowse[2]> ndebug: ret.y <- yBrowse[2]> ndebug: cl <- match.call()Browse[2]> ndebug: mf <- match.call(expand.dots = FALSE)Browse[2]> ndebug: m <- match(c("formula", "data", "subset", "weights", "na.action",  "offset"), names(mf), 0L)Browse[2]> ndebug: mf <- mf[c(1L, m)]Browse[2]> ndebug: mf$drop.unused.levels <- TRUEBrowse[2]> ndebug: mf[[1L]] <- quote(stats::model.frame)Browse[2]> ndebug: mf <- eval(mf, parent.frame())Browse[2]> nError in eval(predvars, data, env) : 找不到对象'y'

调试模式下运行lm(y~x)将打印函数的所有代码,向提示符Browse[2]>一直输入n逐行运行,直到找到出错的那一行。

options(error = recover)#options()设置全局选项,把recover函数设为错误处理器
read.csv("nosuchfile") #读取一个不存在的csv文件Error in file(file, "rt") : 无法打开链结此外: Warning message:In file(file, "rt") : 无法打开文件'nosuchfile': No such file or directory
1: read.csv("nosuchfile")2: read.table(file = file, header = header, sep = sep, quote = quote, dec 3: file(file, "rt")
Selection:

・报错后没有返回控制台,而是输入函数调用栈。

・错误发生在函数调用栈的第3级,当函数试图建立文件关联的时候找不到文件

・输入数字1、2、3,可以浏览函数环境,查看每个调用的函数中都发生了什么

str函数

str 函数可以紧凑地显示 R 对象的内部结构,可以代替 summary 函数,特别适用于大型列表。

➢函数

str(str)function (object, ...)
对str函数本身使用,返回函数的所有参数,它需要一个参数,可以是任何R对象。
➢数值型向量
x <- rnorm(100, 2, 4)summary(x) Min. 1st Qu. Median Mean 3rd Qu. Max. -9.9878 -0.6826 2.5642 2.1066 4.7830 11.2853
str(x) num [1:100] 2.889 0.892 7.577 -0.636 4.642 ...

summary()返回6个概括统计量,粗略说明数据集的范围和离散情况。

str() 说明 x 是一个数值向量,含有100个元素,及向量 x 的前五个数。

➢因子变量
f <- gl(40, 10) str(f) Factor w/ 40 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
summary(f) 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
str()说明变量是因子变量,含有40个水平,各水平名字分别为"1"、"2"、"3"、"4"、……,并输出变量的前几个元素。
s ummary()返回每个水平的元素个数,不像 str 函数的输出那样紧凑。 

➢数据框

library(datasets)head(airquality) Ozone Solar.R Wind Temp Month Day1 41 190 7.4 67 5 12 36 118 8.0 72 5 23 12 149 12.6 74 5 34 18 313 11.5 62 5 45 NA NA 14.3 56 5 56 28 NA 14.9 66 5 6
str(airquality)'data.frame': 153 obs. of 6 variables: $ Ozone : int 41 36 12 18 NA 28 23 19 8 NA ... $ Solar.R: int 190 118 149 313 NA NA 299 99 19 194 ... $ Wind : num 7.4 8 12.6 11.5 14.3 14.9 8.6 13.8 20.1 8.6 ... $ Temp : int 67 72 74 62 56 66 65 59 61 69 ... $ Month : int 5 5 5 5 5 5 5 5 5 5 ... $ Day : int 1 2 3 4 5 6 7 8 9 10 ...

str()说明对象是数据框,有153个观测值,6个变量,输出每个变量的一些元素以及变量类型,为整数型变量和数值型变量。

➢矩阵

m <- matrix(rnorm(100), 10, 10)str(m) num [1:10, 1:10] -0.483 -0.669 0.513 1.049 0.121 ...

str()说明对象是矩阵,有10行10列,并列出前几个元素。

➢列表

s <- split(airquality, airquality$Month) str(s)List of 5 $ 5:'data.frame': 31 obs. of 6 variables: ..$ Ozone : int [1:31] 41 36 12 18 NA 28 23 19 8 NA ... ..$ Solar.R: int [1:31] 190 118 149 313 NA NA 299 99 19 194 ... ..$ Wind : num [1:31] 7.4 8 12.6 11.5 14.3 14.9 8.6 13.8 20.1 8.6 ... ..$ Temp : int [1:31] 67 72 74 62 56 66 65 59 61 69 ... ..$ Month : int [1:31] 5 5 5 5 5 5 5 5 5 5 ... ..$ Day : int [1:31] 1 2 3 4 5 6 7 8 9 10 ... $ 6:'data.frame': 30 obs. of 6 variables: ..$ Ozone : int [1:30] NA NA NA NA NA NA 29 NA 71 39 ... ..$ Solar.R: int [1:30] 286 287 242 186 220 264 127 273 291 323 ... ..$ Wind : num [1:30] 8.6 9.7 16.1 9.2 8.6 14.3 9.7 6.9 13.8 11.5 ... ..$ Temp : int [1:30] 78 74 67 84 85 79 82 87 90 87 ... ..$ Month : int [1:30] 6 6 6 6 6 6 6 6 6 6 ... ..$ Day : int [1:30] 1 2 3 4 5 6 7 8 9 10 ... $ 7:'data.frame': 31 obs. of 6 variables: ..$ Ozone : int [1:31] 135 49 32 NA 64 40 77 97 97 85 ... ..$ Solar.R: int [1:31] 269 248 236 101 175 314 276 267 272 175 ... ..$ Wind : num [1:31] 4.1 9.2 9.2 10.9 4.6 10.9 5.1 6.3 5.7 7.4 ... ..$ Temp : int [1:31] 84 85 81 84 83 83 88 92 92 89 ... ..$ Month : int [1:31] 7 7 7 7 7 7 7 7 7 7 ... ..$ Day : int [1:31] 1 2 3 4 5 6 7 8 9 10 ... $ 8:'data.frame': 31 obs. of 6 variables: ..$ Ozone : int [1:31] 39 9 16 78 35 66 122 89 110 NA ... ..$ Solar.R: int [1:31] 83 24 77 NA NA NA 255 229 207 222 ... ..$ Wind : num [1:31] 6.9 13.8 7.4 6.9 7.4 4.6 4 10.3 8 8.6 ... ..$ Temp : int [1:31] 81 81 82 86 85 87 89 90 90 92 ... ..$ Month : int [1:31] 8 8 8 8 8 8 8 8 8 8 ... ..$ Day : int [1:31] 1 2 3 4 5 6 7 8 9 10 ... $ 9:'data.frame': 30 obs. of 6 variables: ..$ Ozone : int [1:30] 96 78 73 91 47 32 20 23 21 24 ... ..$ Solar.R: int [1:30] 167 197 183 189 95 92 252 220 230 259 ... ..$ Wind : num [1:30] 6.9 5.1 2.8 4.6 7.4 15.5 10.9 10.3 10.9 9.7 ... ..$ Temp : int [1:30] 91 92 93 93 87 84 80 78 75 73 ... ..$ Month : int [1:30] 9 9 9 9 9 9 9 9 9 9 ... ..$ Day : int [1:30] 1 2 3 4 5 6 7 8 9 10 ...

通过month变量来分割airquality数据框,对 s 调用str()。可以看到得到一个包含有5个不同的数据框的列表,每个数据框对应特定的月份,5月有6个变量,31个观测数据。

编辑:李雪纯 冯文清
校审:张健 罗鹏