输出数据帧

时间:2017-06-28 16:53:59

标签: r loops error-handling

问题

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

关于数据的说明:This数据来自NOAA网站,它是Southern Oscillation Index数据。第二组是微不足道的(data2),仅用于生成错误。

这是我尝试创建的循环类型的一个简单的小例子。从Web获取一些数据,对其执行一些操作,存储它(作为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不是有效的网址,因此循环停止并引发错误:

  

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

预期输出

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

  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
}

使用&#34; data2&#34;:

时输出错误
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

1 个答案:

答案 0 :(得分: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
}