【问题标题】:Replacing missing quarter and missing data per quarter替换每季度缺失的季度和缺失的数据
【发布时间】:2018-04-26 02:59:18
【问题描述】:

背景

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

  • 每个组应该有相同数量的季度,但实际上缺少季度
  • 对于缺失的季度值未知
    • 这将通过采购估算下一个可用值来解决;例如,可通过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. 第一个非缺失值应为缺失值结转。

想要的结果:

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

【问题讨论】:

    标签: r dplyr time-series zoo


    【解决方案1】:

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

    【讨论】:

    • 谢谢pad 在这种情况下效果很好;最后,我使用了as.Date 而不是as.POSIXct,因为as.POSIXct 不适用于我拥有的实际日期(并非所有组都有第一个和最后一个日期,所以我必须使用start_valend_val 参数)。
    【解决方案2】:

    使用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" 类中的索引一起使用,无需转换。

    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)
    

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

    【讨论】:

      猜你喜欢
      • 2021-06-12
      • 2023-03-14
      • 2022-11-29
      • 2017-04-05
      • 1970-01-01
      • 2017-08-10
      • 2021-12-19
      • 2017-08-11
      • 2018-12-20
      相关资源
      最近更新 更多