【问题标题】:insert rows between dates by group按组在日期之间插入行
【发布时间】:2018-02-10 00:55:23
【问题描述】:

我想按组在两个日期之间插入行。我这样做的方式非常复杂,以至于我通过最后一次观察结转插入缺失值然后合并。我想知道有没有更简单的方法来实现它。

# sample data 
user<-c("A","A","B","B","B") 
dummy<-c(1,1,1,1,1)
date<-as.Date(c("2017/1/3","2017/1/6","2016/5/1","2016/5/3","2016/5/5"))
dt<-data.frame(user,dummy,date) 

  user dummy       date
1    A     1 2017-01-03
2    A     1 2017-01-06
3    B     1 2016-05-01
4    B     1 2016-05-03
5    B     1 2016-05-05

期望的输出

【问题讨论】:

    标签: r date dataframe


    【解决方案1】:

    Base R(不太优雅)解决方案:

    # Data
    user<-c("A","A","B","B","B") 
    dummy<-c(1,1,1,1,1)
    date<-as.Date(c("2017/1/3","2017/1/6","2016/5/1","2016/5/3","2016/5/5"))
    df1 <-data.frame(user,dummy,date)
    
    # Solution
    do.call(rbind, lapply(split(df1, df1$user), function(df) {
      dff <- data.frame(user=df$user[1], dummy=0, date=seq.Date(min(df$date), max(df$date), 'day'))
      dff[dff$date %in% df$date, "dummy"] <- df$dummy[1]
      dff
    }))
    
    
    # user dummy date      
    # A    1     2017-01-03
    # A    0     2017-01-04
    # A    0     2017-01-05
    # A    1     2017-01-06
    # B    1     2016-05-01
    # B    0     2016-05-02
    # B    1     2016-05-03
    # B    0     2016-05-04
    # B    1     2016-05-05
    

    【讨论】:

      【解决方案2】:

      我发现最简单的方法是使用 padr 库。

      library(padr)
      dt_padded <- pad(dt, group = "user", by = "date") %>%
        replace_na(list(dummy=0))
      

      【讨论】:

      • fillna 到 0 :)
      【解决方案3】:

      通过使用dplyrtidyr :)(单行解决方案)

      library(dplyr)
      library(tidyr)
      dt %>% group_by(user) %>% complete(date=full_seq(date,1),fill=list(dummy=0))
      # A tibble: 9 x 3
      # Groups:   user [2]
          user       date dummy
        <fctr>     <date> <dbl>
      1      A 2017-01-03     1
      2      A 2017-01-04     0
      3      A 2017-01-05     0
      4      A 2017-01-06     1
      5      B 2016-05-01     1
      6      B 2016-05-02     0
      7      B 2016-05-03     1
      8      B 2016-05-04     0
      9      B 2016-05-05     1
      

      【讨论】:

        【解决方案4】:

        假设您的数据名为 df1,并且您想在两天之间添加日期,请尝试以下操作:

        library(dplyr)
        df2 <- seq.Date(as.Date("2015-01-03"), as.Date("2015-01-06"), by ="day")
        left_join(df2, df1)
        

        如果您只是想添加一条新记录,我建议使用 rbind。

        rbind()
        

        【讨论】:

          【解决方案5】:

          我们可以使用tidyverse来完成这个任务。

          library(tidyverse)
          
          dt2 <- dt %>%
            group_by(user) %>%
            do(date = seq(from = min(.$date), to = max(.$date), by = 1)) %>%
            unnest() %>%
            left_join(dt, by = c("user", "date")) %>%
            replace_na(list(dummy = 0)) %>%
            select(colnames(dt))
          
          dt2
          # A tibble: 9 x 3
              user dummy       date
            <fctr> <dbl>     <date>
          1      A     1 2017-01-03
          2      A     0 2017-01-04
          3      A     0 2017-01-05
          4      A     1 2017-01-06
          5      B     1 2016-05-01
          6      B     0 2016-05-02
          7      B     1 2016-05-03
          8      B     0 2016-05-04
          9      B     1 2016-05-05
          

          【讨论】:

            【解决方案6】:

            你可以试试这个

            library(data.table)
            setDT(dt)
            tmp <- dt[, .(date = seq.Date(min(date), max(date), by = '1 day')), by = 
            'user']
            dt <- merge(tmp, dt, by = c('user', 'date'), all.x = TRUE)
            dt[, dummy := ifelse(is.na(dummy), 0, dummy)]
            

            【讨论】:

            • 只有一个建议,OP 正在处理data.frame :)
            猜你喜欢
            • 1970-01-01
            • 2013-10-03
            • 2016-01-15
            • 1970-01-01
            • 2021-12-17
            • 2021-03-22
            • 1970-01-01
            • 2019-07-22
            • 1970-01-01
            相关资源
            最近更新 更多