【问题标题】:Error handling in a loop that outputs a dataframe输出数据帧的循环中的错误处理
【发布时间】:2017-12-02 04:08:22
【问题描述】:

问题

我正在尝试在 R 中编写一个循环,我预计会出现一些错误。我没有停止循环,而是试图找出一种方法来捕获错误消息并将该信息包含在输出中并继续循环。

关于数据的注意事项:This 数据来自 NOAA 网站,它是南方涛动指数数据。第二组是微不足道的(data2),仅用于生成错误。

这是我尝试创建的循环类型的一个简单示例。从网络上获取一些数据,对其执行一些操作,将其存储(作为df)然后获取更多数据,执行相同的操作并将其(通过rbind)附加到第一个数据:

data_spec <- c("data")
df <- c()
for (i in data_spec){
  raw <- read.csv(
    paste0("https://www.ncdc.noaa.gov/teleconnections/enso/indicators/soi/",i,".csv"),
           skip = 2, col.names = c("Date","SOI") )
  u <- data.frame(data_spec = i, mean_soi = mean(raw$SOI))
  df <- rbind(df, u)
}

因为https://www.ncdc.noaa.gov/teleconnections/enso/indicators/soi/data2.csv不是有效的url,所以循环停止并抛出错误:

文件中的错误(文件,“rt”):无法打开连接另外: 警告消息:在文件中(文件,“rt”):无法打开 URL 'https://www.ncdc.noaa.gov/teleconnections/enso/indicators/soi/data2.csv': HTTP 状态为“未找到 404”

预期输出

我正在尝试实现这样的输出,其中错误消息被捕获为对象并相应地附加:

  data_spec                                             mean_soi
1      data                                            0.1223618
2     data2 Error in file(file, rt) : cannot open the connection

试图解决这个问题

所以我想我很清楚我需要在这里使用tryCatch。如果我这样使用它:

data_spec <- c("data", "data2")
df <- c()
for (i in data_spec){
  tryCatch({
  raw <- read.csv(
    paste0("https://www.ncdc.noaa.gov/teleconnections/enso/indicators/soi/",i,".csv"),
    skip = 2, col.names = c("Date","SOI") )
  u <- data.frame(data_spec = i, mean_soi = mean(raw$SOI))
  df <- rbind(df, u)
  }, error=function(e){cat("ERROR :",conditionMessage(e), "\n")})
}

循环继续进行,但输出中未捕获错误消息(不是我在这里期待的)。

另一种选择是使用从demo(error.catching) 输出的函数。我稍微修改了该函数,以便捕获错误消息:

tryCatch_mod <- function(expr)
{
  W <- NULL
  w.handler <- function(w){ # warning handler
    W <<- w
    invokeRestart("muffleWarning")
  }
  temp <- list(value = withCallingHandlers(tryCatch(expr, error = function(e) e),
                                   warning = w.handler),
       warning = W)

  unlist(temp[[2]])$message
}

使用“data2”时会输出错误:

tryCatch_mod(read.csv("https://www.ncdc.noaa.gov/teleconnections/enso/indicators/soi/data2.csv",
                      skip = 2, col.names = c("Date","SOI")))

我想不通

如何包含此函数(或完成相同任务的函数)以便输出是有条件的或是否有错误?也就是说,我该如何编写它本质上说的函数:

  • 出现错误时,跳过任何操作并将i 和错误消息附加到df
  • 当没有错误时,执行操作并将结果附加到相同的df

【问题讨论】:

    标签: r loops error-handling


    【解决方案1】:

    我重新创建您的 data.frame 以包含一个额外的列来存储错误消息,因为在 R data.frame 中,一列应该存储一种类型的东西。将错误消息和其他内容存储在一个列中将是一团糟,并且它们的类型将被强制相同。 handle_i 函数是您要对每个 i 执行的函数。错误处理是tryCatch 行,它会在发生错误时返回您要存储的错误消息(但它不会对警告做任何事情)。最后把东西对应到data.frame里去。

    handle_i <- function(i){
        raw <- read.csv(
            paste0("https://www.ncdc.noaa.gov/teleconnections/enso/indicators/soi/",i,".csv"),
            skip = 2, col.names = c("Date","SOI") )
        list(mean_soi = mean(raw$SOI))
    }
    
    data_spec <- c("data", "data2")
    df <- data.frame(data_spec = data_spec, mean_soi = NA, message = "", stringsAsFactors = FALSE)
    for (i in 1:length(data_spec)) {
        r <- tryCatch(handle_i(data_spec[i]), error = function(e) list(message = e$message))
        df[i, names(r)] <- r
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-24
      • 1970-01-01
      • 1970-01-01
      • 2011-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多