每季度更换丢失的季度和缺失的数据

时间:2017-11-13 12:13:39

标签: r dplyr time-series zoo

背景

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

  • 每个小组应该相同数量的季度,但在实际宿舍中缺少
  • 缺少季度值未知
    • 这是通过寻找下一个可用值来解决的;例如,可通过na.locf函数
    • 获得

示例数据

# 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. 应该为缺失值继续使用第一个非缺失值。

  3. 期望的结果:

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

2 个答案:

答案 0 :(得分:2)

您似乎对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

答案 1 :(得分:1)

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

我们可以省略:

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

这不会使用问题尚未使用的任何软件包,而是直接使用原始"yearqtr"类中的索引而不进行转换。

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)

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