【问题标题】:Add fixed number of rows for each group with values based on another column为每个组添加固定数量的行,其值基于另一列
【发布时间】:2019-07-08 03:43:54
【问题描述】:

我有一个包含 ID 和每个 ID 的干预开始日期的大型数据框:

  ID Date
1 1  17228
2 2  17226
3 3  17230

我想在每个 ID 中添加 2 行,并将后续日期作为这些行中的值:

  ID Date
1 1  17228
2 1  17229
3 1  17230
4 2  17226
5 2  17227
6 2  17228
7 3  17230
8 3  17231
9 3  17232

如果可能的话,有什么方法可以使用 dplyr 吗?其他方式也可以!

【问题讨论】:

  • 只做df1[rep(seq_len(nrow(df1)), each = 3),] 或使用tidyverse df1 %>% uncount(3)
  • 行的日期需要增加,而不是重复!
  • 好的,在这种情况下df1 %>% uncount(3) %>% group_by(ID) %>% mutate(Date = seq(Date[1], length.out = n(), by = 1))
  • 有点令人困惑的是,当我标记了一个骗子时,它又被重新打开了。这只是一件简单的事情

标签: r dplyr


【解决方案1】:

我们通过uncounting扩展数据,然后按'ID'分组,得到sequence从first'Date'到行数(n())同时递增by 1

library(tidyverse)
df1 %>%
  uncount(3) %>% 
  group_by(ID) %>% 
  mutate(Date = seq(Date[1], length.out = n(), by = 1))
# A tibble: 9 x 2
# Groups:   ID [3]
#     ID  Date
#  <int> <dbl>
#1     1 17228
#2     1 17229
#3     1 17230
#4     2 17226
#5     2 17227
#6     2 17228
#7     3 17230
#8     3 17231
#9     3 17232

或者另一个选项是unnest list

df1 %>%
   group_by(ID) %>% 
   mutate(Date = list(Date[1] + 0:2)) %>% 
   unnest

或者complete

df1 %>%
   group_by(ID) %>%
   complete(Date = first(Date) + 0:2)

或使用base R(从 cmets 粘贴)

within(df1[rep(seq_len(nrow(df1)), each = 3),], Date <- Date + 0:2)

或者更简洁的data.table

library(data.table)
setDT(df1)[, .(Date = Date  + 0:2), ID]

【讨论】:

    【解决方案2】:
    do.call(rbind, lapply(split(d, d$ID), function(x){
        rbind(x, data.frame(ID = rep(tail(x$ID, 1), 2),
                            Date = tail(x$Date, 1) + 1:2))
    }))
    #     ID  Date
    #1.1   1 17228
    #1.11  1 17229
    #1.2   1 17230
    #2.2   2 17226
    #2.1   2 17227
    #2.21  2 17228
    #3.3   3 17230
    #3.1   3 17231
    #3.2   3 17232
    

    数据

    d = structure(list(ID = 1:3, Date = c(17228L, 17226L, 17230L)),
                  class = "data.frame",
                  row.names = c("1", "2", "3"))
    

    【讨论】:

      【解决方案3】:

      使用dplyr,我们可以将每一行重复3次,group_byID,并为每个ID将每个日期从0增加到n() - 1

      library(dplyr)
      
      df %>%
        slice(rep(seq_len(n()), each = 3)) %>%
        group_by(ID) %>%
        mutate(Date = Date + 0: (n() - 1))
      
      #    ID  Date
      #  <int> <int>
      #1     1 17228
      #2     1 17229
      #3     1 17230
      #4     2 17226
      #5     2 17227
      #6     2 17228
      #7     3 17230
      #8     3 17231
      #9     3 17232
      

      使用上述相同逻辑的基本 R 单线将是

      transform(df[rep(seq_len(nrow(df)), each = 3),], Date = Date + 0:2)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-07-28
        • 1970-01-01
        • 2021-08-25
        • 1970-01-01
        • 1970-01-01
        • 2022-08-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多