每季度替换缺失的季度和缺失的数据

Replacing missing quarter and missing data per quarter

背景

我有一个季度数据集,其中缺少某些季度和相应的值。数据集的特点是:

示例数据

# Packages
Vectorize(require)(package = c("tidyverse", "zoo", "magrittr"),
                   character.only = TRUE)

# Seed
set.seed(123)

# Dummy data
dta <- data.frame(group = rep(LETTERS[1:5], 10)) %>%
    group_by(group) %>%
    mutate(qrtr = seq(
        from = as.Date("01/01/2012", "%d/%m/%Y"),
        to = as.Date("31/5/2014", "%d/%m/%Y"),
        by = "quarter"
    )) %>%
    ungroup() %>%
    mutate(qrtr = as.yearqtr(qrtr)) %>%
    arrange(group, qrtr) %>%
    mutate(value = sample(1:10, 50, replace = TRUE))

# Remove random rows
dta[sample(1:dim(dta)[1], 10), c(2, 3)] <- NA
dta %<>% na.omit()

预览

# A tibble: 40 x 3
   group          qrtr value
   <chr> <S3: yearqtr> <int>
 1     A       2012 Q1     3
 2     A       2012 Q2     8
 3     A       2012 Q4     9
 4     A       2013 Q1    10
 5     A       2013 Q3     6
 6     A       2013 Q4     9
 7     A       2014 Q1     6
 8     B       2012 Q1    10
 9     B       2012 Q2     5
10     B       2012 Q3     7
# ... with 30 more rows

问题

  1. 在缺少四分之一的每个组中创建添加行。在现有代码的上下文中,季度总数从序列 min(qrtr)max(qrtr) 得出:

    seq(from = as.Date("01/01/2012", "%d/%m/%Y"),
        to = as.Date("31/5/2014", "%d/%m/%Y"),
        by = "quarter")
    
  2. 第一个非缺失值应为缺失值结转

想要的结果:

>> dta
# A tibble: 50 x 3
   group          qrtr value
   <chr> <S3: yearqtr> <int>
 1     A       2012 Q1     3
 2     A       2012 Q2     8
 3     A       2012 Q3     8
 4     A       2012 Q4     9
 5     A       2013 Q1    10
 6     A       2013 Q2    10
 7     A       2013 Q3     6
 8     A       2013 Q4     9
 9     A       2014 Q1     6
10     A       2015 Q1     6
# ... with 40 more rows

提议的方法

一种方法依赖于使用 expand,以便将隐式缺失值转换为显式缺失值。到目前为止,这会创建缺失的季度,但没有明确的方法可以为缺少给定季度的 value 列创建缺失的观察值。

dta %>%
    # Append mixing quarters
    expand(group, qrtr) %>% 
    left_join(data.frame(qrtr = as.yearqtr(
        seq(
            from = as.Date("01/01/2012", "%d/%m/%Y"),
            to = as.Date("31/5/2014", "%d/%m/%Y"),
            by = "quarter"
        )
    )), by = "qrtr") %>%
    # TODO
    # mutate(value = na.locf(value)) %>% 
    arrange(group, qrtr) -> dta_fixed

您似乎对padr

感兴趣
library(padr)
library(zoo)

#convert to POSIXct as pad() expect it to be like this
dta$qrtr <- as.POSIXct(dta$qrtr,format="%Y %q")
dta %>% 
  pad(group="group") %>% 
  arrange(group, qrtr) %>%
  mutate(qrtr = as.yearqtr(qrtr)) %>%
  na.locf()

输出为:

# A tibble: 49 x 3
   group    qrtr value
   <chr>   <chr> <chr>
 1     A 2012 Q1     3
 2     A 2012 Q2     8
 3     A 2012 Q3     8
 4     A 2012 Q4     9
 5     A 2013 Q1    10
 6     A 2013 Q2    10
 7     A 2013 Q3     6
 8     A 2013 Q4     9
 9     A 2014 Q1     6
10     B 2012 Q1    10
# ... with 39 more rows

使用read.zoo创建多变量时间序列z,每组一列;将其与零宽度系列的四分之一 运行 na.locf 合并,然后将其转换回长格式。

我们可以省略:

  • 带有 merge 的行,如果每个组都没有遗漏四分之一——在问题的示例数据中就是这种情况。即对于问题中的数据,我们可以省略 merge(尽管如果我们将其保留在其中不会造成问题)
  • 最后一行(带 fortify.zoo 的那一行)如果我们可以直接使用 10 x 5 多元时间序列 z,这实际上可能更方便,例如library(ggplot); autoplot(z, facet = NULL) + scale_x_yearqtr() 或没有 facet 参数的相同参数将使用 ggplot2 图形使用 1 或 5 个面板绘制它。

这不使用问题尚未使用的任何包,而是直接使用原始 "yearqtr" class 中的索引,无需转换。

library(zoo)

z <- read.zoo(dat, index = "qrtr", split = "group")
z <- merge(z, zoo(, seq(start(z), end(z), 1/4))
z <- na.locf(z)
fortify.zoo(z, melt = TRUE)

这也可以表示为以下管道:

library(dplyr) # or library(magrittr)
library(zoo)

dta %>%
    read.zoo(index = "qrtr", split = "group") %>%
    merge(zoo(, start(z), end(z), 1/4)) %>%
    na.locf %>%
    fortify.zoo(melt = TRUE)

更新 添加了管道并进行了一些措辞改进和澄清。