【问题标题】:Fill missing dates by group按组填写缺失的日期
【发布时间】:2018-07-15 22:50:54
【问题描述】:

在我的数据中,在某些月份存在某些 ID 的观察结果,而对其他 ID 则没有,例如

dat <- data.frame(c(1, 1, 1, 2, 3, 3, 3, 4, 4, 4), c(rep(30, 2), rep(25, 5), rep(20, 3)), c('2017-01-01', '2017-02-01', '2017-04-01', '2017-02-01', '2017-01-01', '2017-02-01', '2017-03-01', '2017-01-01',
                    '2017-02-01', '2017-04-01'))
colnames(dat) <- c('id', 'value', 'date')

我想为每个 id 值插入一个行,其中包含该 idNA 缺失的月份(对于 value)。

有没有办法(在某种程度上)在seq(min(as.Date(dat$date)), max(as.Date(dat$date)), by = 'months') 的所有月份中简洁地执行此操作?我经常使用 tidyverse 和 data.table,但对任何方法都持开放态度。

【问题讨论】:

标签: r dplyr missing-data


【解决方案1】:

tidyr::complete() 填补缺失值

添加 iddate 作为列 (...) 以扩展

library(tidyverse)

complete(dat, id, date)


# A tibble: 16 x 3
      id date       value
   <dbl> <date>     <dbl>
 1  1.00 2017-01-01  30.0
 2  1.00 2017-02-01  30.0
 3  1.00 2017-03-01  NA  
 4  1.00 2017-04-01  25.0
 5  2.00 2017-01-01  NA  
 6  2.00 2017-02-01  25.0
 7  2.00 2017-03-01  NA  
 8  2.00 2017-04-01  NA  
 9  3.00 2017-01-01  25.0
10  3.00 2017-02-01  25.0
11  3.00 2017-03-01  25.0
12  3.00 2017-04-01  NA  
13  4.00 2017-01-01  20.0
14  4.00 2017-02-01  20.0
15  4.00 2017-03-01  NA  
16  4.00 2017-04-01  20.0

【讨论】:

    【解决方案2】:

    这是一种使用expand.gridmerge 的方法:

    dat <- data.frame(c(1, 1, 1, 2, 3, 3, 3, 4, 4, 4), c(rep(30, 2), rep(25, 5), rep(20, 3)), as.Date(c('2017-01-01', '2017-02-01', '2017-04-01', '2017-02-01', '2017-01-01', '2017-02-01', '2017-03-01', '2017-01-01',
                                                                                                '2017-02-01', '2017-04-01')))
    colnames(dat) <- c('id', 'value', 'date')
    
    date_range <- seq(min(as.Date(dat$date)), max(as.Date(dat$date)), by = 'months')
    
    dat_expanded <- expand.grid(date_range, dat$id)
    
    colnames(dat_expanded) <- c("date", "id")
    
    result <- merge(dat, dat_expanded, by=c("id", "date"), all.y = T)
    

    【讨论】:

      【解决方案3】:

      tidyr::complete() 根据您的示例数据起作用:

      library(tidyverse)
      dat %>% 
        group_by(id) %>% 
        complete(date) %>% 
        ungroup()
      
            id date       value
         <dbl> <fct>      <dbl>
       1  1.00 2017-01-01  30.0
       2  1.00 2017-02-01  30.0
       3  1.00 2017-03-01  NA  
       4  1.00 2017-04-01  25.0
       5  2.00 2017-01-01  NA  
       6  2.00 2017-02-01  25.0
       7  2.00 2017-03-01  NA  
       8  2.00 2017-04-01  NA  
       9  3.00 2017-01-01  25.0
      10  3.00 2017-02-01  25.0
      11  3.00 2017-03-01  25.0
      12  3.00 2017-04-01  NA  
      13  4.00 2017-01-01  20.0
      14  4.00 2017-02-01  20.0
      15  4.00 2017-03-01  NA  
      16  4.00 2017-04-01  20.0
      

      【讨论】:

      • 这行得通,但它比它需要的要复杂一些。您可以简单地提供iddate 作为在complete 中展开的列,避免分组和取消分组。
      猜你喜欢
      • 2020-05-07
      • 1970-01-01
      • 2018-06-24
      • 2020-11-10
      • 2023-03-05
      • 2018-10-05
      • 2019-06-26
      相关资源
      最近更新 更多