【问题标题】:r - Adding rows by group so that every group has at least n observationsr - 按组添加行,以便每个组至少有 n 个观察值
【发布时间】:2019-12-20 17:03:50
【问题描述】:

我正在使用如下结构的数据框:

structure(list(Date = structure(c(1L, 2L, 3L, 1L, 2L, 3L, 4L, 
5L, 1L, 2L), .Label = c("2010-02-01", "2010-03-01", "2010-04-01", 
"2010-05-01", "2010-06-01"), class = "factor"), y = c(1, 1, 1, 
2, 2, 2, 2, 2, 3, 3), binary = c(0, 0, 0, 0, 0, 0, 1, 1, 0, 1
)), class = "data.frame", row.names = c(NA, -10L))


        Date  y binary
1  2010-02-01 1      0
2  2010-03-01 1      0
3  2010-04-01 1      0
4  2010-02-01 2      0
5  2010-03-01 2      0
6  2010-04-01 2      0
7  2010-05-01 2      1
8  2010-06-01 2      1
9  2010-02-01 3      0
10 2010-03-01 3      1 

我正在努力让每个组至少有四个连续的逐月观察,条件是一旦二进制假设组的 value = 1,它就会保持这种状态.结果应如下所示:

         Date   y binary
>1  2010-02-01  1   0
>2  2010-03-01  1   0
>3  2010-04-01  1   0
>4  2010-05-01  1   0
>5  2010-02-01  2   0
>6  2010-03-01  2   0
>7  2010-04-01  2   0
>8  2010-05-01  2   1
>9  2010-06-01  2   1
>10 2010-02-01  3   0
>11 2010-03-01  3   1
>12 2010-04-01  3   1
>13 2010-05-01  3   1

我为第一组 (y = 1) 创建了一个数据子集,下面的循环适用于此。

dt1 <- dt[1:3,]
maxdate<- 0
while(nrow(dt1) < 5){maxdate <- as.Date(dt1[nrow(dt1), 1])  %m+% months(1) ;  dt1<- rbind(dt1, c(as.character(maxdate) , dt1[nrow(dt1),2], dt1[nrow(dt1),3]))}

但我不知道如何将此函数合并到像 dt %&gt;% group_by(y) 这样的 dplyr 结构中。

我如何获得我的结果,最好使用 dplyr,如果可能,不重复 for 循环?(实际数据集非常大)。

【问题讨论】:

    标签: r for-loop dplyr as.date


    【解决方案1】:

    这是一个选项,我们首先将“日期”转换为 Date 类,按“y”分组,获取行数(每组 n()),然后使用该信息扩展“日期” ' 在complete 中,这样每组至少有 4 行,fill NA 元素与先前的非 NA 并删除创建的临时 'n' 列

    library(dplyr)
    library(tidyr)
    df1 %>%
       mutate(Date = as.Date(Date)) %>%
       group_by(y) %>% 
       mutate(n = n()) %>%
       complete(Date = seq(first(Date), length.out = max(first(n), 4),
               by = '1 month')) %>%
       fill(binary) %>%
       select(-n)
    # A tibble: 13 x 3
    # Groups:   y [3]
    #      y Date       binary
    #   <dbl> <date>      <dbl>
    # 1     1 2010-02-01      0
    # 2     1 2010-03-01      0
    # 3     1 2010-04-01      0
    # 4     1 2010-05-01      0
    # 5     2 2010-02-01      0
    # 6     2 2010-03-01      0
    # 7     2 2010-04-01      0
    # 8     2 2010-05-01      1
    # 9     2 2010-06-01      1
    #10     3 2010-02-01      0
    #11     3 2010-03-01      1
    #12     3 2010-04-01      1
    #13     3 2010-05-01      1
    

    【讨论】:

    • 谢谢!这非常有帮助。我注意到使用 zoo 包中的 na.locf() 是一种比 fill() 更有效地填写剩余列的方法,并且可以在几秒钟内完成工作,而不是几天。
    【解决方案2】:

    一种选择是创建一个包含您想要的所有日期的新表,然后将其滚动连接到您的原始表 df,然后根据需要将 nafill 其他列。

    library(lubridate)
    library(data.table)
    setDT(df)
    df[, Date := as.Date(Date)]
    
    alldts <- 
      df[, if(.N < 4) .(Date = first(Date) + months(0:3)) else Date,  by = y]
    
    df[alldts, on = .(y, Date), roll = -Inf
       ][, binary := nafill(binary, 'locf')][]
    
    #           Date y binary
    #  1: 2010-02-01 1      0
    #  2: 2010-03-01 1      0
    #  3: 2010-04-01 1      0
    #  4: 2010-05-01 1      0
    #  5: 2010-02-01 2      0
    #  6: 2010-03-01 2      0
    #  7: 2010-04-01 2      0
    #  8: 2010-05-01 2      1
    #  9: 2010-06-01 2      1
    # 10: 2010-02-01 3      0
    # 11: 2010-03-01 3      1
    # 12: 2010-04-01 3      1
    # 13: 2010-05-01 3      1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-23
      • 2016-04-22
      • 1970-01-01
      • 2019-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-04
      相关资源
      最近更新 更多