Tuesday, March 31, 2015php
以前用rvest帮人写了一个按期抓取amazon价格库存,并与以前价格比较的小程序,算是近期写过的第一个完整的程序了。里面涉及了一些报错的处理。html
这里主要参考了stackoverflow上的如下问答:java
tryCatch部分,后续查找资料,发现如下博文: 1. R语言使用tryCatch进行简单的错误处理express
如下是代码示例:小程序
1)使用tryCatch函数跳过错误信息。(示例以download.file为样式)less
看如下代码。这里须要批量下载一堆amazon产品信息。若是产品ID号不对,或者IP被限制,网页会打不开,而download.file会报错。我这里用tryCatch来获取网页打不开时的错误信息。而且要求执行下一步循环“”。ide
for (n in 1:length(productlink)){ tryCatch({ download.file(productlink[n],paste0(getwd(),"/html/",productid[n,],".html"),cacheOK = TRUE) },error=function(e){cat("ERROR :",conditionMessage(e),"\n")}) Sys.sleep(0.5) #增长了Sys.sleep(seconds)函数,让每一步循环都暂停一段时间。这个虽然会下降程序速度,但对于有访问限制的网站,不失为一个好的办法。 }
上述示例由两个重要函数构成,即tryCatch和cat函数
查阅函数,tryCatch属于base包,condition system。在R语言使用tryCatch进行简单的错误处理这篇博文里有tryCatch的简单示范以下:oop
result = tryCatch( {expr}, warning = function(w) {warning-handler-code}, error = function(e) { error-handler-code}, finally = {cleanup-code} )
即若是warning时,对warning怎么处理,若是error时对error怎么处理。若是没有任何条件吻合,则最后会输出expr里的内容。若是有final项的话,则会同时输出finally项以及expr项布局
tryCatch({a<-"c" b<-"c" b==a}, error=function(e){cat("hahaha",conditionMessage(e),"\n\n")}, finally={print("ccc")})
[1] "ccc"
[1] TRUE
tryCatch({a<-"c"
cc==a}, #cc不存在 error=function(e){cat("hahaha",conditionMessage(e),"\n\n")}, finally={print("ccc")})
hahaha object 'cc' not found
对于代码示例,即为,download成功则返回download内容,不成功则返回error=function(e){cat("ERROR :",conditionMessage(e),"\n")}
而后是cat函数。这个cat是一个输入输出值。这里等于,要求系统输出“ERROR :”+conditionMessage(e)的内容。而后用“”分行。
另外,在stackoverflow上的这篇问答,由mmann1123回答的问题里,咱们看到了更为有趣的一个应用。
这里收缩起来,展开亦可阅读。
#!/usr/bin/env Rscript # tryCatch.r -- experiments with tryCatch # Get any arguments arguments <- commandArgs(trailingOnly=TRUE) a <- arguments[1] # Define a division function that can issue warnings and errors myDivide <- function(d, a) { if (a == 'warning') { return_value <- 'myDivide warning result' warning("myDivide warning message") } else if (a == 'error') { return_value <- 'myDivide error result' stop("myDivide error message") } else { return_value = d / as.numeric(a) } return(return_value) } # Evalute the desired series of expressions inside of tryCatch result <- tryCatch({ b <- 2 c <- b^2 d <- c+2 if (a == 'suppress-warnings') { e <- suppressWarnings(myDivide(d,a)) } else { e <- myDivide(d,a) # 6/a } f <- e + 100 }, warning = function(war) { # warning handler picks up where error was generated print(paste("MY_WARNING: ",war)) b <- "changing 'b' inside the warning handler has no effect" e <- myDivide(d,0.1) # =60 f <- e + 100 return(f) }, error = function(err) { # warning handler picks up where error was generated print(paste("MY_ERROR: ",err)) b <- "changing 'b' inside the error handler has no effect" e <- myDivide(d,0.01) # =600 f <- e + 100 return(f) }, finally = { print(paste("a =",a)) print(paste("b =",b)) print(paste("c =",c)) print(paste("d =",d)) # NOTE: Finally is evaluated in the context of of the inital # NOTE: tryCatch block and 'e' will not exist if a warning # NOTE: or error occurred. #print(paste("e =",e)) }) # END tryCatch print(paste("result =",result))
2)利用if语句以及stop语句。
即,若是某条件不成立,则中止程序,并输出stop里的内容。我这里主要用于检查原始product id是否输入正确。
if (!sum(check)==length(productlink)) { productlink<-NULL productid<-NULL stop("invalid productid please double check if any space or else in, and resave the file or the script will not run") }
3)处理使用data.frame批量读取数据时,元素由于不存在致使的data.frame报错。
譬如说如下示例,由于a不存在,而致使data.frame报错。
a<-NULL b<-c("cc","dd") data.frame(a,d) > Error in data.frame(a, d) : 参数值意味着不一样的行数: 0, 2
所以,对于在循环里,须要先单独合成data.frame,再使用rbind把各个data.frame合成在一块儿时,能够考虑增长异常值的赋值。以下面两段,若是我拉的网页里不存在product name,则length(productname)==1为FALSE,直接输出“product not download or not existing”,那么这个字段就不是空值或者2-3个行,而是1行,以后合并为data.frame时就不会报错了。
data<-function(n){ ####隐掉得到productname/price/category的代码 if(!length(productname)==1) {productname="Product not download or not existing"} if (!length(price)==1) { price=NA category<-"Product not download or not existing" } data.frame(productname,price,category) #这里合成data.frame,若是这三个行数不等(多为空值NULL,或者某个字段有2-3行所致使。 #使用上面的IF判断赋值的好处是,最后出来的productname,price,category保证是1行,能够用data.frame合并。而且对异常值也有输出。
因为处理第2/3类错误时我还不了解tryCatch函数。目前看下来,貌似tryCatch函数能作的事情更多?
写下来供之后写代码时参考。
另外,tryCatch在java,C里均有相似功效。看来R归根到底,仍是脱离不了底层语言啊。
接下来4月的学习计划,学完一个就写一篇博文~~整理思路记录笔记。
1)rCurl包,以及它那个厚厚的英文说明书。但愿最后能学会用它爬一些rvest没法爬的脚本网页,以及搜索框网页等
2)用R作金融时间序列分析(炼数成金的班)
3)跟着肖星老师从新复习财务分析知识(mooc课),在复习过去的财务知识后,再从新来看预测者网下的股票数据,尝试作一下挖掘与分析,至少从宏观上了解当前中国上市公司的布局与特色,为之后用R研究股票打打基础。
----------
个人博客: http://www.cnblogs.com/weibaar 记录学习R与数据分析的一切。