【问题标题】:If error, next iteration in a for loop in R如果错误,则在 R 中的 for 循环中进行下一次迭代
【发布时间】:2017-01-15 07:28:10
【问题描述】:

如果 for 循环内的操作出错,我正在寻找一种简单的方法来继续 R 中 for 循环中的下一次迭代。

我在下面重新创建了一个简单的案例:

for(i in c(1, 3)) {
  test <- try(i+1, silent=TRUE)
  calc <- if(class(test) %in% 'try-error') {next} else {i+1}
  print(calc)
}

这正确地给了我以下计算值。

[1] 2
[1] 4

但是,一旦我将 i 中的向量更改为包含非数字值:

for(i in c(1, "a", 3)) {
  test <- try(i+1, silent=TRUE)
  calc <- if(class(test) %in% 'try-error') {next} else {i+1}
  print(calc)
}

这个 for 循环不起作用。我希望得到与上面相同的计算值,向量不包括 i 中的非数字值。

我尝试使用 tryCatch 如下:

for(i in c(1, "a", 3)) {
  calc <- tryCatch({i+1}, error = function(e) {next})
  print(calc)
}

但是,我收到以下错误:

Error in value[[3L]](cond) : no loop for break/next, jumping to top level 

有人可以帮我理解如何在 R 中使用 for 循环来实现这一点吗?

【问题讨论】:

  • 您可能想检查c(1, "a", 3) 的实际含义。我认为您认为只有中间元素是字符,但这是不正确的。
  • 我不确定你为什么要这样做。这是一个简化的例子吗?如果不是,那么仅在输入向量上使用as.numeric 将使字符变为 NA。玩弄它as.numeric(c(1, "k", "3")) + 1
  • @Dason 实际上,我对 for 循环示例中控制流的错误处理更感兴趣,因为这只是我拥有的较大脚本的简化案例。我只是通过放置一个字符元素来重新创建一个抛出“错误”的场景,从而违反了 i 中向量的定义。希望这能澄清我的问题。
  • 您在示例中创建的问题是您创建了所有错误。你没有留下一个好的案例。
  • 你想从中得到什么输出?你想要一个错误所在的向量,还是一个有效结果的向量?

标签: r for-loop error-handling try-catch next


【解决方案1】:

正如 Dason 所说,原子向量确实不是存储混合数据类型的最佳方式。列表就是为此。考虑以下几点:

l = list(1, "sunflower", 3)

for(i in seq_along(l)) {
   this.e = l[[i]]
   test <- try(this.e + 1, silent=TRUE)
   calc <- if(class(test) %in% 'try-error') {next} else {this.e + 1}
   print(calc)
}

[1] 2
[1] 4

换句话说,您以前的循环“有效”。它只是总是失败并进入下一次迭代。

【讨论】:

    【解决方案2】:

    这是一个使用“purr”包的解决方案,可能会有所帮助。 它会遍历您的列表或向量并返回会导致错误的元素

    #Wrap the function you want to use in the adverb "safely" 
    safetest <- safely(function(x){ifelse(is.na(as.numeric(x)),
                                      x+1,
                                      as.numeric(x)+1)})
    
    myvect<-c(1,"crumbs",3) #change to list if you want a list
    
    #Use the safe version to find where the errors occur
    check <- myvect  %>% 
      map(safetest) %>%
      transpose %>% .$result %>% 
      map_lgl(is_null)
    
    myvect[check]
    
    #This returns the results that did not through an error
    #first remove NULL elements then flatten to double.
    #The two flatten expresiion can be replaced by a single unlist
    myvect  %>% 
      map(safetest) %>%
      transpose %>% .$result %>% 
      flatten()%>%flatten_dbl()
    

    原始示例请参见 https://blog.rstudio.org/2016/01/06/purrr-0-2-0/

    【讨论】:

      猜你喜欢
      • 2018-07-24
      • 2015-11-11
      • 1970-01-01
      • 2020-05-09
      • 2021-05-15
      • 1970-01-01
      • 2013-07-02
      • 1970-01-01
      • 2021-12-20
      相关资源
      最近更新 更多