【问题标题】:Inserting missing time observations in a dataframe在数据框中插入缺失的时间观察
【发布时间】:2015-07-01 18:43:07
【问题描述】:

我有一个数据框:

zz <- "Product    Quarter   Million
AAA 2013-Q3 81.1
AAA 2013-Q4 50.5
AAA 2014-Q1 81.9
AAA 2014-Q4 78.3
BBB 2013-Q3 29.9
BBB 2013-Q4 17
BBB 2014-Q3 87.4
BBB 2014-Q4 63
CCC 2013-Q4 41.1
CCC 2014-Q1 59.1
CCC 2014-Q2 110.7
CCC 2014-Q3 127"

df <- read.table(text = zz, header = TRUE); rm(zz)

观察跨越:

2013-Q3 2013-Q4 2014-Q1 2014-Q2 2014-Q3 2014-Q4

除了,大多数Products 都缺少时间观察。

我需要将缺失的句点作为零插入:

Product Quarter Million
AAA 2013-Q3 81.1
AAA 2013-Q4 50.5
AAA 2014-Q1 81.9
AAA 2014-Q2 0
AAA 2014-Q3 0
AAA 2014-Q4 78.3
BBB 2013-Q3 29.9
BBB 2013-Q4 0
BBB 2014-Q1 0
BBB 2014-Q2 0
BBB 2014-Q3 87.4
BBB 2014-Q4 63
CCC 2013-Q3 0
CCC 2013-Q4 41.1
CCC 2014-Q1 59.1
CCC 2014-Q2 110.7
CCC 2014-Q3 127
CCC 2014-Q4 0

【问题讨论】:

    标签: r time-series dplyr forecasting


    【解决方案1】:

    以下两种解决方案都假设每个季度至少出现在一个产品中,就像问题中的情况一样:

    1) xtabs 此解决方案不需要任何包:

     xt <- xtabs(Million ~ Quarter + Product, df)
     as.data.frame(xt, responseName = "Million")[c(2, 1, 3)]
    
       Product Quarter Million
    1      AAA 2013-Q3    81.1
    2      AAA 2013-Q4    50.5
    3      AAA 2014-Q1    81.9
    4      AAA 2014-Q2     0.0
    5      AAA 2014-Q3     0.0
    6      AAA 2014-Q4    78.3
    7      BBB 2013-Q3    29.9
    8      BBB 2013-Q4    17.0
    9      BBB 2014-Q1     0.0
    10     BBB 2014-Q2     0.0
    11     BBB 2014-Q3    87.4
    12     BBB 2014-Q4    63.0
    13     CCC 2013-Q3     0.0
    14     CCC 2013-Q4    41.1
    15     CCC 2014-Q1    59.1
    16     CCC 2014-Q2   110.7
    17     CCC 2014-Q3   127.0
    18     CCC 2014-Q4     0.0
    

    如果列顺序和列名不必与问题中的完全相同,则可以将其缩短为:

    as.data.frame(xtabs(Million ~ Quarter + Product, df))
    

    如果宽格式可以,那么它可以进一步缩短为:

    xtabs(Million ~ Quarter + Product, df)
    

    给予:

             Product
    Quarter     AAA   BBB   CCC
      2013-Q3  81.1  29.9   0.0
      2013-Q4  50.5  17.0  41.1
      2014-Q1  81.9   0.0  59.1
      2014-Q2   0.0   0.0 110.7
      2014-Q3   0.0  87.4 127.0
      2014-Q4  78.3  63.0   0.0
    

    2) zoodf 转换为 zoo 对象 z,然后将每个 NA 替换为零并使用 fortify.zoomelt=TRUE 参数将其转换回长表。

    library(zoo)
    
    z <- read.zoo(df, index = 2, FUN = identity, split = 1, header = TRUE)
    z <- na.fill(z, 0)
    df_full <- fortify.zoo(z, melt = TRUE, name = "Product")[, c(2, 1, 3)]
    names(df_full) <- names(df)
    

    给予:

    > df_full
       Product Quarter Million
    1      AAA 2013-Q3    81.1
    2      AAA 2013-Q4    50.5
    3      AAA 2014-Q1    81.9
    4      AAA 2014-Q2      NA
    5      AAA 2014-Q3      NA
    6      AAA 2014-Q4    78.3
    7      BBB 2013-Q3    29.9
    8      BBB 2013-Q4    17.0
    9      BBB 2014-Q1      NA
    10     BBB 2014-Q2      NA
    11     BBB 2014-Q3    87.4
    12     BBB 2014-Q4    63.0
    13     CCC 2013-Q3      NA
    14     CCC 2013-Q4    41.1
    15     CCC 2014-Q1    59.1
    16     CCC 2014-Q2   110.7
    17     CCC 2014-Q3   127.0
    18     CCC 2014-Q4      NA
    

    如果宽格式 "zoo" 对象可以,则省略最后两行,即省略设置 df_full 及其名称的行,只使用 z

    > z
             AAA  BBB   CCC
    2013-Q3 81.1 29.9   0.0
    2013-Q4 50.5 17.0  41.1
    2014-Q1 81.9  0.0  59.1
    2014-Q2  0.0  0.0 110.7
    2014-Q3  0.0 87.4 127.0
    2014-Q4 78.3 63.0   0.0
    

    【讨论】:

      【解决方案2】:

      你可以试试:

      library(data.table)
      setkey(setDT(df), Product, Quarter)[CJ(unique(Product), unique(Quarter))][!df, Million:=0][]
      
      #    Product Quarter Million
      # 1:     AAA 2013-Q3    81.1
      # 2:     AAA 2013-Q4    50.5
      # 3:     AAA 2014-Q1    81.9
      # 4:     AAA 2014-Q2     0.0
      # 5:     AAA 2014-Q3     0.0
      # 6:     AAA 2014-Q4    78.3
      # 7:     BBB 2013-Q3    29.9
      # 8:     BBB 2013-Q4    17.0
      # 9:     BBB 2014-Q1     0.0
      #10:     BBB 2014-Q2     0.0
      #11:     BBB 2014-Q3    87.4
      #12:     BBB 2014-Q4    63.0
      #13:     CCC 2013-Q3     0.0
      #14:     CCC 2013-Q4    41.1
      #15:     CCC 2014-Q1    59.1
      #16:     CCC 2014-Q2   110.7
      #17:     CCC 2014-Q3   127.0
      #18:     CCC 2014-Q4     0.0
      

      【讨论】:

      • 还有:with(df, CJ(Product=unique(Product), Quarter=unique(Quarter)))[, Million := 0][df, Million := i.Million][]
      【解决方案3】:

      您可以使用reshape2 包来做到这一点:

      library(reshape2)    
      df <- melt(dcast(df, Product ~ Quarter))
      

      然后您可以将 NA 值更改为 0:

      df[is.na(df)] <- 0
      

      【讨论】:

        【解决方案4】:

        试试这个

        Values = as.data.frame(table(df$Product,df$Quarter))
        Values = Values[with(Values, order(Var1, Var2)), ]
        colnames(Values)[1] = 'Product'
        colnames(Values)[2] = 'Quarter'
        
        data = merge(x = Values, y = df, by =c("Product","Quarter"), all.x=TRUE)
        data[is.na(data)] <- 0
        data = data[,c(1,2,4)]
        

        【讨论】:

          【解决方案5】:

          对于R 的人来说,也许解决方案有点过于冗长,但它使用的是dplyr

          # all products from your dataframe
          product <- unique(df$Product) # all products from your dataframe
          # all quarters you want
          quarter <- c('2013-Q3', '2013-Q4', '2014-Q1', '2014-Q2', '2014-Q3', '2014-Q4')
          # let's combine them
          df2 <- expand.grid(Product=product, Quarter = quarter)
          
          # and now let's do a join between your df and all possible 
          # combinations of Products and Quarters
          df %>%
            right_join(df2) %>%                               # here the join
            arrange(Product, Quarter) %>%                     # here the sorting
            mutate(Value = ifelse(is.na(Million),0, Million)) # replacing the NA with 0
          

          【讨论】:

            猜你喜欢
            • 2016-01-05
            • 1970-01-01
            • 2015-09-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-04-12
            相关资源
            最近更新 更多