• R语言-处理异常值或报错的三个示例



    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),"
    ")})
            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),"
    
    ")},
            finally={print("ccc")})

    [1] "ccc"
    [1] TRUE

    tryCatch({a<-"c"

             cc==a}, #cc不存在
            error=function(e){cat("hahaha",conditionMessage(e),"
    
    ")},
            finally={print("ccc")})
    hahaha object 'cc' not found 

    对于代码示例,即为,download成功则返回download内容,不成功则返回error=function(e){cat("ERROR :",conditionMessage(e)," ")}

    然后是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

     

  • 相关阅读:
    table变宽格式
    IE11兼容性设定
    Spring AOP注解失效的坑及JDK动态代理
    关于何时执行shiro AuthorizingRealm 里的 doGetAuthenticationInfo与doGetAuthorizationInfo
    后端接收json数据交互
    关于JavaDate数据返回到前端变数字的问题(并引申到前后端时间的传输)
    git 列出两个分支 或者两个提交版本之间不同的文件名字
    map put相同的key
    MyBatis 中如何调用 Java 的 enum (枚举) 字段
    @ResponseBody 和 @RequestBody 的作用
  • 原文地址:https://www.cnblogs.com/weibaar/p/4382397.html
Copyright © 2020-2023  润新知