如何在使用purrr时定位错误并进行调试

11

当使用purrr和一些map()变体时,我发现调试代码很困难。特别是当出错信息没有告诉我哪一行(数据框)抛出了错误时,我会遇到问题。

在使用purrr时,如何定位错误?

考虑以下示例:

library(tidyverse)

# Prepare some data
set.seed(1)
a <- tibble(
  x = rnorm(2),
  y = rnorm(2))

b <- tibble(
  x = rnorm(2),
  y = rnorm(2))

c <- tibble(
  x = rnorm(2),
  y = letters[1:2])

df <- tibble(
  dataframes = list(a,b,c))

df
#> # A tibble: 3 x 1
#>   dataframes      
#>   <list>          
#> 1 <tibble [2 x 2]>
#> 2 <tibble [2 x 2]>
#> 3 <tibble [2 x 2]>

# A simple function 
add_cols <- function(.data){
  .data %>% 
    mutate(
      z = x + y)
}

# Running the function with map() will return an error
df %>% 
  mutate(
    dataframes = map(.x = dataframes, ~add_cols(.x)))
#> Error in x + y: non-numeric argument to binary operator

map() 返回一个错误,因为您不能将数字和字母相加。错误消息告诉我们出了什么问题,但没有告诉我们具体的错误位置。df 中第三行是错误的显而易见的位置,但假设函数更加复杂,并且我们正在对成千上万个行应用它,那么如何找到错误位置呢?

到目前为止,我的方法是使用某种版本的循环来查找错误。我认为这种方法的缺点非常明显。请帮助我找到更好的方法。

for(i in 1:nrow(df)){
  print(paste("Testing row number", i))

  df %>% 
    filter(row_number() == i) %>% 
    unnest(cols = c(dataframes)) %>% 
    add_cols()
}
#> [1] "Testing row number 1"
#> [1] "Testing row number 2"
#> [1] "Testing row number 3"
#> Error in x + y: non-numeric argument to binary operator

如果与您的建议相关,我正在使用Rstudio。

reprex软件包(v0.3.0)于2019-10-15创建


你可以使用 possiblysafelytryCatch 提取错误/警告信息。 - akrun
1个回答

10
我们可以使用purrr中的possiblysafely函数,并指定otherwise
library(dplyr)
library(purrr)
out <- df %>%
         mutate(dataframes = map(dataframes, ~ 
                possibly(add_cols, otherwise = 'error here')(.x)))

out$dataframes
#[[1]]
# A tibble: 2 x 3
#       x      y     z
#   <dbl>  <dbl> <dbl>
#1 -0.626 -0.836 -1.46
#2  0.184  1.60   1.78

#[[2]]
# A tibble: 2 x 3
#       x     y       z
#   <dbl> <dbl>   <dbl>
#1  0.330 0.487  0.817 
#2 -0.820 0.738 -0.0821

#[[3]]
#[1] "error here"

可以通过简单的检查找到

out$dataframes %in%  'error here'
#[1] FALSE FALSE  TRUE
要找到位置,请用which进行包装。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接