R中不规则时间序列的插值

7
在R中搜索时间序列数据的线性插值时,我经常发现建议使用zoo包中的na.approx()。然而,对于不规则时间序列,我遇到了问题,因为插值值在缺口数量上平均分布,而不考虑值的相关时间戳。我找到了一个解决方法,使用approxfun(),但是我想知道是否有更清洁的解决方案,最好基于tsibble对象并使用tidyverts包系列的函数?以前的答案依赖于通过填充缺口将不规则日期网格扩展为正则网格。然而,在插值过程中需要考虑白天时间时,这会导致问题。下面是一个(修订后的)最小示例,其中使用的是POSIXct时间戳而不是仅日期:
library(tidyverse)
library(zoo)

df <- tibble(date = as.POSIXct(c("2000-01-01 00:00", "2000-01-02 02:00", "2000-01-05 00:00")),
             value = c(1,NA,2))

df %>% 
  mutate(value_int_wrong = na.approx(value),
         value_int_correct = approxfun(date, value)(date))

# A tibble: 3 x 4
  date                value value_int_wrong value_int_correct
  <dttm>              <dbl>           <dbl>             <dbl>
1 2000-01-01 00:00:00     1             1                1   
2 2000-01-02 02:00:00    NA             1.5              1.27
3 2000-01-05 00:00:00     2             2                2   

有没有关于(高效)处理这个的想法?感谢您的支持!


嗨,Jens,你找到了令人满意的解决方案吗?我很感兴趣。 - mabe
2个回答

5
这里提供了一种基于tsibble的等效方案。 interpolate() 函数需要一个模型,但是你可以使用随机游走来在各点之间进行线性插值。
library(tidyverse)
library(tsibble)
library(fable)
#> Loading required package: fabletools

df <- tibble(
  date = as.Date(c("2000-01-01", "2000-01-02", "2000-01-05", "2000-01-06")),
  value = c(1, NA, 2, 1.5)
) %>%
  as_tsibble(index = date) %>%
  fill_gaps()

df %>%
  model(naive = ARIMA(value ~ -1 + pdq(0,1,0) + PDQ(0,0,0))) %>%
  interpolate(df)
#> # A tsibble: 6 x 2 [1D]
#>   date       value
#>   <date>     <dbl>
#> 1 2000-01-01  1   
#> 2 2000-01-02  1.25
#> 3 2000-01-03  1.5 
#> 4 2000-01-04  1.75
#> 5 2000-01-05  2   
#> 6 2000-01-06  1.5

本示例由 reprex 包 (v0.3.0) 在 2020-04-08 创建


嗨,Rob,非常感谢你的回答。我希望你能看一下!我不得不修改我的最小示例,因为实际上我处理的是解决了一天中时间的时间序列。我尝试在我的修订后的数据集上运行您的代码,但这导致出现错误消息(“找不到适当的ARIMA模型。这很可能是因为自动选择不会选择具有可能数值不稳定的特征根的模型。”)。您的解决方案是否可以应用于POSIXct?感谢分享您的专业知识! - Jens Daniel Müller
我更新了我的答案,以便在POSIXct混淆选择季节模型时更具体。如果仍然导致错误,请在https://github.com/tidyverts/fable/issues上发布一个可重现的示例的错误报告。 - Rob Hyndman
嗨,Rob,再次感谢,但它似乎不能在我的最小示例中运行。我在 https://github.com/tidyverts/fable/issues/256 上开了一个问题。 - Jens Daniel Müller

0

个人而言,我会选择您正在使用的解决方案,但为了展示如何在这种情况下使用na.approx,我们可以在使用na.approx之前完成日期序列,并将其与原始的df连接起来以保留原始行。

library(dplyr)

df %>% 
  tidyr::complete(date = seq(min(date), max(date), by = "day")) %>%
  mutate(value_int = zoo::na.approx(value)) %>%
  right_join(df, by = "date") %>%
  select(date, value_int)


#  date       value_int
#  <date>         <dbl>
#1 2000-01-01      1   
#2 2000-01-02      1.25
#3 2000-01-05      2   

嗨Ronak,感谢您的即时回答。恐怕您提出的解决方案只适用于日期向量具有高时间分辨率的情况?我在我的最小示例中没有涵盖这一点,但通常我正在处理的环境时间序列具有秒级分辨率,但仍然每隔几天才进行测量。 - Jens Daniel Müller
嗯,它可能效率不高,但我认为它仍然可以工作。 - Ronak Shah

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