【问题标题】:Creating a ts time series with missing values from a data frame从数据框中创建具有缺失值的 ts 时间序列
【发布时间】:2019-02-27 10:47:02
【问题描述】:

我有一个数据框,其中包含一个时间序列的月度数据,其中有一些缺失值。

dates <- seq(
  as.Date("2010-01-01"), as.Date("2017-12-01"), "1 month"
)
n_dates <- length(dates)
dates <- dates[runif(n_dates) < 0.5]
time_data <- data.frame(
  date = dates,
  value = rnorm(length(dates))
)
##          date      value
## 1  2010-02-01  1.3625419
## 2  2010-06-01  0.1512481
## etc.

为了能够在 forecast 等中使用时间序列预测功能,我想将其转换为 ts 对象。

执行此操作的愚蠢方法是在整个时间段内创建一组定期的每月日期,然后将左连接返回到原始数据。

library(dplyr)
first_date <- min(time_data$date)
last_date <- max(time_data$date)
full_dates <- data.frame(
  date = seq(first_date, last_date, "1 month")
)
extended_time_data <- left_join(full_dates, time_data, by = "date")
##          date      value
## 1  2010-02-01  1.3625419
## 2  2010-03-01         NA
## etc.

现在我可以使用ts() 创建时间序列。

library(lubridate)
time_series <- ts(
  extended_time_data$value, 
  start = c(year(first_date), month(first_date)),
  frequency = 12
)

对于这样一个简单的任务,这是冗长而粗暴的。

我还研究过首先转换为xts,并使用timetk 包中的转换器,但没有什么比我更简单的方法了。

这个问题是How to create time series with missing datetime values的骗子,但那里的答案更模糊。

如何根据缺少值的时间序列创建 ts 对象?

【问题讨论】:

  • 什么是n_dates 试试expand time_data %&gt;% expand(date = seq(min(date),max(date), by = "1 month"), select(., everything(), -date))
  • 我认为n_dates 应该是length(seq( as.Date("2010-01-01"), as.Date("2017-12-01"), "1 month" ))
  • 您还缺少 lubridate 包来访问您的示例代码中的 year / month 等。

标签: r time-series missing-data


【解决方案1】:

一个base 选项并在运行数据生成之前使用set.seed(789)

temp <- which(full_dates$date%in%time_data$date)
full_dates$new[temp] <- time_data$value
head(full_dates, 20)

         date         new
1  2010-02-01  0.62589399
2  2010-03-01  0.98117664
3  2010-04-01          NA
4  2010-05-01 -0.04770986
5  2010-06-01 -1.51961483
6  2010-07-01          NA
7  2010-08-01  0.79493644
8  2010-09-01 -0.14423251
9  2010-10-01 -0.70649791
10 2010-11-01  0.61071247
11 2010-12-01          NA
12 2011-01-01  1.08506164
13 2011-02-01 -0.71134925
14 2011-03-01  1.15628805
15 2011-04-01  1.23556280
16 2011-05-01 -0.32245531
17 2011-06-01          NA
18 2011-07-01          NA
19 2011-08-01  0.73277540
20 2011-09-01 -0.28752883

或相同的结果,但使用data.table

setDT(full_dates)[temp, new:= time_data$value]

现在到xts

xts::xts(full_dates[,-1], order.by = full_dates$date,  frequency = 12 )

【讨论】:

    【解决方案2】:

    使用最后注释中定义的输入数据框,将其转换为索引为yearmon 类的动物园对象。然后as.ts 会将其转换为ts

    library(zoo)
    
    z <- read.zoo(DF, FUN = as.yearmon)
    as.ts(z)
    ##      Jan Feb Mar Apr May Jun Jul Aug
    ## 2000   1  NA  NA   2   3  NA   4   5
    

    如果您更喜欢用管道表示:

    library(magrittr)
    library(zoo)
    
    DF %>% read.zoo(FUN = as.yearmon) %>% as.ts
    

    如果需要,使用na.locf(最后一次结转)、na.approx(线性插值)、na.splinena.StructTS(季节性卡尔曼滤波器)或其他 zoo NA 填充函数对时间序列中的值进行插值.例如

    library(forecast)
    
    DF %>% read.zoo(FUN = as.yearmon) %>% as.ts %>% na.spline %>% forecast
    

    注意

    问题中的数据不可重现,因为在没有set.seed 的情况下使用随机数,并且n_dates 未定义。下面我们以可重复的方式定义一个数据框DF,以作为示例。

    library(zoo)
    
    dates <- as.Date(as.yearmon("2000-01") + c(0, 3, 4, 6, 7)/12)
    DF <- data.frame(dates, values = seq_along(dates))
    

    给予:

    > DF
           dates values
    1 2000-01-01      1
    2 2000-04-01      2
    3 2000-05-01      3
    4 2000-07-01      4
    5 2000-08-01      5
    

    【讨论】:

      【解决方案3】:

      不使用left_join,更简单的选择是complete,将其转换为现在与forecast 包函数兼容的tsibble 对象

      library(tidyverse)
      library(tsibble)
      time_data %>% 
        complete(date = seq(min(date), max(date), by = "1 month"), 
              fill = list(value = NA)) %>%
        as_tsibble(index = date)
      
      
      # A tsibble: 94 x 2 [1D]
      #   date         value
      #   <date>       <dbl>
      # 1 2010-02-01   1.02 
      # 2 2010-03-01  NA    
      # 3 2010-04-01  NA    
      # 4 2010-05-01   1.75 
      # 5 2010-06-01  NA    
      # 6 2010-07-01  NA    
      # 7 2010-08-01  -0.233
      # 8 2010-09-01  NA    
      # 9 2010-10-01  NA    
      #10 2010-11-01  -0.987
      # ... with 84 more rows
      

      如上所述,兼容forecast函数

      library(fable)
      time_data %>% 
         complete(date = seq(min(date), max(date), by = "1 month"), 
               fill = list(value = 0)) %>% 
         as_tsibble(index = date) %>%
         ETS(value) %>% 
         forecast %>%
         autoplot
      

      注意:这里,缺失值被估算为 0。

      可以用fill之前的非NA值估算

      time_data %>% 
         complete(date = seq(min(date), max(date), by = "1 month")) %>% 
         fill(value) %>% 
         as_tsibble(index = date) %>% 
         ETS(value) %>%
         forecast %>%
         autoplot
      

      数据

      n_dates <- 3
      

      【讨论】:

        猜你喜欢
        • 2016-11-21
        • 2011-08-28
        • 2016-11-04
        • 1970-01-01
        • 1970-01-01
        • 2021-05-27
        • 2019-11-21
        • 2020-02-19
        • 1970-01-01
        相关资源
        最近更新 更多