Mutate_at 无法插入组时停止,tryCatch 不起作用

Mutate_at stops when it cannot interpolate a group, tryCatch does not work

我有数据如下:

library(data.table)
DT <- structure(list(country = c("Germany", "Germany", "Germany", "Germany", 
"Germany", "France", "France", "France", "France", "France", 
"UK", "UK", "UK", "UK", "UK"), year = c(2000, 2001, 2002, 2003, 
2004, 2000, 2001, 2002, 2003, 2004, 2000, 2001, 2002, 2003, 2004
), a = c(NA, NA, NA, NA, NA, NA, 1000, NA, 1600, NA, 1000, NA, 
1000, NA, NA), b = c(NA, NA, NA, NA, NA, NA, 1000, NA, 2200, 
NA, 1000, NA, 1000, NA, NA)), row.names = c(NA, -15L), class = c("data.table", 
"data.frame"))

我正在尝试插入一些值。

我试图重现这个错误(这当然是一个非常合乎逻辑的错误,因为没有德国的数据):

Error: Problem with `mutate()` input `a`.
x need at least two non-NA values to interpolate
i Input `count` is `(structure(function (..., .x = ..1, .y = ..2, . = ..1) ...`.
i The error occurred in group 123: value = "group", country = "Arthur", State = "Nebraska".
Run `rlang::last_error()` to see where the error occurred.

使用以下代码:

library(tidyverse)
library(zoo)
st_example %>%
  group_by(country) %>%
  mutate_at(vars(a),~na.fill(.x,c(NA, "extend", NA))) %>% 
  filter(!is.na(a))

很遗憾没有收到预期的错误。

我的问题是,当 mutate_at 失败时,它不会继续进行下一组。我试图围绕 mutate_at(vars(a:b),~na.fill(.x,c(NA, "extend", NA))) %>% 构建一个 tryCatch 但没有成功。

如果遇到错误,我如何告诉 mutate_at 继续?

您的错误是由 zoo::na.fill 而不是 mutate_at() 引发的。 运行 rlang::last_error() 从控制台会浮出水面。

zoo::na.fill(c("hello",NA), c(NA, "extend", NA))
Error in approx(wix, unlist(object[wix]), xout = wrng) : 
  need at least two non-NA values to interpolate

你可以用这样的东西来破解它:

DT %>%
  group_by(country) %>%
  mutate_at(
    vars(a),
    ~ tryCatch(
        as.numeric(na.fill(.x,c(NA, "extend", NA))),
        error = function(error) .x
    )
  ) %>%
  filter(!is.na(a))

顺便说一句,没有理由在示例代码中使用 data.table - dplyr 会将 data.table 对象强制转换为 data.frame.

以下内容无需使用 tryCatch() 即可工作:

DT %>%
  split(.$country) %>%
  purrr::map(~mutate(., a = as.numeric(na.fill(.x$a, c(NA, "extend", NA))))) %>%
  bind_rows()

如果目标是按国家/地区对 a 列执行线性插值,则:

library(dplyr)
library(zoo)

DT %>% 
  group_by(country) %>%
  mutate(a = na.approx(a, na.rm = FALSE)) %>%
  ungroup

或插入所有数值列:

DT %>% 
  group_by(country) %>%
  mutate(across(where(is.numeric), ~ na.approx(., na.rm = FALSE))) %>%
  ungroup