【问题标题】:Interpolate between non-NA observations在非 NA 观测值之间进行插值
【发布时间】:2020-01-06 00:27:05
【问题描述】:

考虑对不规则快照的观察,其中一些是 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 值,应该有插值)我认为以某种方式使用 leadlag。此代码在所有值之间进行插值:

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"))

【问题讨论】:

    标签: r dplyr interpolation


    【解决方案1】:

    我们可以创建一个新列来标记我们不想插入的非 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  
    

    【讨论】:

    • 这并没有回答我关于仅在非 NA 观测值之间插值的问题
    • @qwr 你能用预期的输出更新你的帖子,以便我清楚吗?
    • @qwr 我已经更新了答案,请检查是否是你想要的。
    • 答案非常接近我的预期。我唯一的疑虑是使用 0 作为标记值,​​而 value 很容易为零(这与乘法有关)。但无论如何我都会给你一个赞成票。
    • completefill 的使用是不错的技巧。我正在使用带有新数据框的连接来填写日期,并使用na.locf 进行观察。
    【解决方案2】:

    这是我设想的解决方案。主要思想是创建一个掩码来确定哪些值将被插值。要创建掩码,如果该行和下一行都具有非 NA 值,我们将一行标记为 TRUE,然后使用 completefill 填充它们之间。为了完成掩码,我们将最后一个连续观察设置为 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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-20
      • 1970-01-01
      • 1970-01-01
      • 2022-11-08
      • 2015-07-21
      • 2018-06-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多