#r #syntax #interpolation #na #dplyr
#r #синтаксис #интерполяция #na #dplyr
Вопрос:
У меня есть следующие данные:
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
сбое он не переходит к следующей группе. Я пытался построить a tryCatch
вокруг mutate_at(vars(a:b),~na.fill(.x,c(NA, "extend", NA))) %>%
, но безуспешно.
Как мне указать mutate_at
продолжить, если он обнаружит ошибку?
Ответ №1:
Ваша ошибка выдается 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
.
Ответ №2:
Следующее должно работать без использования tryCatch():
DT %>%
split(.$country) %>%
purrr::map(~mutate(., a = as.numeric(na.fill(.x$a, c(NA, "extend", NA))))) %>%
bind_rows()
Ответ №3:
Если целью является выполнение линейной интерполяции по столбцам 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