Tuesday, March 31, 2015

之前用rvest帮人写了一个定期抓取amazon价格库存,并与之前价格比较的小程序,算是近期写过的第一个完整的程序了。里面涉及了一些报错的处理。

这里主要参考了stackoverflow上的以下问答:

  1. How to skip an error in a loop
  2. skip to next value of loop upon error in R

tryCatch部分,后续查找资料,发现以下博文: 1. R语言使用tryCatch进行简单的错误处理

以下是代码示例:

1)使用tryCatch函数跳过错误信息。(示例以download.file为样式)

看以下代码。这里需要批量下载一堆amazon产品信息。如果产品ID号不对,或者IP被限制,网页会打不开,而download.file会报错。我这里用tryCatch来获取网页打不开时的错误信息。并且要求执行下一步循环“”。

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的简单示范如下:

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))

tryCatch示范

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与数据分析的一切。

博客总目录:http://www.cnblogs.com/weibaar/p/4507801.html

R语言-处理异常值或报错的三个示例的更多相关文章

  1. R语言安装openxl包报错解决办法

    在R语言中使用openxlsx包,会报错 解决办法就是: 下载安装Set-Rtool,安装时注意勾选对话框 然后在R中运行以下代码: Sys.setenv("R_ZIPCMD" = ...

  2. R语言安装sqldb包报错解决办法

    我使用Rtudio环境,安装sqldb几次出错.网上没有好的教程. 经过自己试验之后,这样处理.我写出来以后,供大家参考. > install.packages("sqldf" ...

  3. zTree实现地市县三级级联报错(三)

    zTree实现地市县三级级联报错(三) 1.具体报错如下 usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] ...

  4. C语言扩展动态内存报错:realloc(): invalid next size: 0x0000000002365010 ***

    晚上被这个内存扩展崩溃的问题折腾的有点崩溃,当答案揭晓的那一刻,恍然大悟,原来如此简单. 练习题目:输入一个字符串,根据字母进行排序,说白了就是一个简单的冒泡 #include <stdio.h ...

  5. 【R笔记】glm函数报错原因及解析

    R语言glm函数学习:  [转载时请注明来源]:http://www.cnblogs.com/runner-ljt/ Ljt 作为一个初学者,水平有限,欢迎交流指正. glm函数介绍: glm(for ...

  6. servlet上传文件报错(三)

    1.具体报错如下 null null Exception in thread "http-apr-8686-exec-5" java.lang.OutOfMemoryError: ...

  7. 安装STS报错(三)

    安装STS报错 1.具体报错如下 Failure to transfer org.codehaus.plexus:plexus-archiver:jar:1.2 from http://repo.ma ...

  8. android r.styleable是什么或报错

    r.styleable 是自定义控件 自定义控件写好的后,需要在res-value-attrs.xml中定义,如: <declare-styleable name="SlidingMe ...

  9. EOS签名R值过大导致报错"is_canonical( c ): signature is not canonical"

    简要 EOS中规定签名的R和S必须同时小于N/2才是合法的签名. 详细 EOS签名交易相对BTC和ETH来说,对签名的要求更加严格了. BTC中bip62规定了((Low S values in si ...

随机推荐

  1. Virtualbox虚机无法启动因断电

      The virtual machine 'nn1' has terminated unexpectedly during startup with exit code 1 (0x1). More ...

  2. UVA10048 Audiophobia[Floyd变形]

    UVA - 10048 Audiophobia Consider yourself lucky! Consider yourself lucky to be still breathing and h ...

  3. python有超时的windows系统时间设置代码

    手边的笔记本用久了,cmos电池可能又没电了.每次开机时间都不对,导致访问一些有https的网页会出现警告信息. 于是找了找通过python脚本设置系统时间的方法,发现了两种,其一是调用socket直 ...

  4. Server Tomcat v6.0 Server at localhost was unable to start within 45 seconds...

    仰天长啸   Server Tomcat v6.0 Server at localhost was unable to start within 45 seconds... 当启动tomcat时候出现 ...

  5. codevs 1015 计算器的改良 2000年NOIP全国联赛普及组

     时间限制: 1 s  空间限制: 128000 KB  题目等级 : 白银 Silver 题目描述 Description NCL是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委 ...

  6. LUA类

    cpp_object_map = {}setmetatable(cpp_object_map, { __mode = "kv" }) local search_basesearch ...

  7. AppBox升级进行时 - 关联表查询与更新(Entity Framework)

    AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. 关联表的查询操作 使用 Include 方法,我们可以在一次数据库查询中将关联 ...

  8. VS2012的调试插件Image Watch,opencv编程神器

    今天配置 opencv3.0 时无意中看到 Image Watch 这样一个VS2012的调试插件,适用了下,特别好用. 部分链接: Image Watch 的 下载链接 OpenCV关于ImageW ...

  9. 代码比较器 Araxis Merge

    Araxis Merge 是一个可视化的文件比较.合并和同步的软件,能够方便的被软件工程师和 web 站点开发者使用快速精确地比较.了解和联合不同版本的源文件:进行版本和质量控制,创建 HTML 或是 ...

  10. ceph rgw s3 java sdk 上传大文件分批的方法

    Using the AWS Java SDK for Multipart Upload (High-Level API) Topics Upload a File Abort Multipart Up ...