Интерполировать между наблюдениями не-NA - PullRequest
0 голосов
/ 06 января 2020

Рассмотрим наблюдения на нерегулярных снимках, некоторые из которых представляют собой NA:

library(tidyverse)
library(tweenr)
df <- data.frame(date = c(ymd("20191201"), ymd("20191203"), ymd("20191207"), ymd("20191220")),
                 value = c(1, 2, NA, 5))

Каков самый чистый способ линейной интерполяции дат только между наблюдениями со значениями не-NA ? (В этом примере, поскольку 20191201 и 20191203 имеют последовательные значения не-NA, должна быть интерполяция) Я думаю, что-то, используя lead или lag. Этот код интерполирует между всеми значениями:

all_days <- data.frame(date = seq(min(df$date), max(df$date), "day"))
df %>% 
  arrange(date) %>%
  right_join(all_days) %>%
  mutate(value = value %>% tween_fill("linear"))

Ответы [ 2 ]

1 голос
/ 06 января 2020

Мы можем создать новый столбец, чтобы отмечать даты, которые находятся между значениями не-NA, которые мы не хотим интерполировать (temp). Используйте complete для заполнения отсутствующей последовательности дат и fill столбец temp и используйте na.approx для интерполяции значений.

library(tidyr)
library(zoo)
library(dplyr)

df %>%
  mutate(temp = +(!(is.na(value) | lead(is.na(value), default = TRUE)))) %>%
  complete(date = seq(min(date), max(date), by = "day")) %>%
  fill(temp) %>%
  mutate(temp = replace(temp, !is.na(value), 1),
        value = na.approx(value) * temp) %>%
  na_if(0) %>% select(-temp)


# A tibble: 20 x 2
#   date       value
#   <date>     <dbl>
# 1 2019-12-01   1  
# 2 2019-12-02   1.5
# 3 2019-12-03   2  
# 4 2019-12-04  NA  
# 5 2019-12-05  NA  
# 6 2019-12-06  NA  
# 7 2019-12-07  NA  
# 8 2019-12-08  NA  
# 9 2019-12-09  NA  
#10 2019-12-10  NA  
#11 2019-12-11  NA  
#12 2019-12-12  NA  
#13 2019-12-13  NA  
#14 2019-12-14  NA  
#15 2019-12-15  NA  
#16 2019-12-16  NA  
#17 2019-12-17  NA  
#18 2019-12-18  NA  
#19 2019-12-19  NA  
#20 2019-12-20  5  
0 голосов
/ 06 января 2020

Вот мое предполагаемое решение. Основная идея заключается в создании маски, которая определяет, какие значения будут интерполироваться. Чтобы создать маску, мы помечаем строку как TRUE, если и строка, и следующая строка имеют значение, отличное от NA, затем используем complete и fill для заполнения между ними. Чтобы завершить маску, мы установили для последнего смежного наблюдения значение TRUE.

df %>%
  mutate(has_value = !is.na(value),
         mask = lead(has_value, default = FALSE) & has_value) %>%
  complete(date = seq(min(date), max(date), by = "day"),
           fill = list(has_value = FALSE)) %>%
  fill(mask) %>%
  mutate(mask = mask | has_value,
         value = if_else(mask, value %>% tween_fill("linear"), NA_real_)) %>%
  select(-has_value, -mask)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...