调试工具debugging tools
➢条件condition
用于提示运行函数过程中意外事件或错误的发生,编写函数时可以自行创造新的提示条件。
- message:由message()产生,输出提示信息到Console控制台,不会阻止函数运行
- warning:由warning()产生,运行过程出现潜在的问题,函数继续执行,完全执行后输出警告
- error:由stop()产生,运行过程出现重大问题无法继续,强制终止运行
#warninglog(-1)[1] NaNWarning message:In log(-1) : 产生了NaNs#取一个负数的常用对数,返回NaN表示非数字 (Not a number)#errorprintmessage 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 foundtraceback()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 ret.y cl mf m "offset"), names(mf), 0L) mf mf$drop.unused.levels mf[[1L]] mf ... if (!qr) z$qr z} Browse[2]> n debug: ret.x Browse[2]> ndebug: ret.y Browse[2]> ndebug: cl Browse[2]> ndebug: mf Browse[2]> ndebug: m "offset"), names(mf), 0L)Browse[2]> ndebug: mf Browse[2]> ndebug: mf$drop.unused.levels Browse[2]> ndebug: mf[[1L]] Browse[2]> ndebug: mf 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 directory1: 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 summary(x) Min. 1st Qu. Median Mean 3rd Qu. Max. -9.9878 -0.6826 2.5642 2.1066 4.7830 11.2853str(x) num [1:100] 2.889 0.892 7.577 -0.636 4.642 ...
summary()返回6个概括统计量,粗略说明数据集的范围和离散情况。
str() 说明 x 是一个数值向量,含有100个元素,及向量 x 的前五个数。
➢因子变量
f 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"、……,并输出变量的前几个元素。
summary()返回每个水平的元素个数,不像 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 6str(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 str(m) num [1:10, 1:10] -0.483 -0.669 0.513 1.049 0.121 ...
str()说明对象是矩阵,有10行10列,并列出前几个元素。
➢列表
s 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个观测数据。