【问题标题】:R - Duplicating rows based on a sequence of start and end datesR - 根据开始和结束日期的序列复制行
【发布时间】:2015-10-17 00:10:52
【问题描述】:

我有一个这样的数据框“DF”:

Flight.Start   Flight.End   Device      Partner   Creative   Days.in.Flight 
2015-08-31     2015-08-31   Standard    MSN       Video      35

我需要做的是像这样“炸毁它”:

Flight.Start   Flight.End   Date         Device      Partner   Creative   Days.in.Flight 
2015-08-31     2015-10-04   2015-08-31   Standard    MSN       Video      35
2015-08-31     2015-10-04   2015-09-01   Standard    MSN       Video      35
2015-08-31     2015-10-04   2015-09-02   Standard    MSN       Video      35
2015-08-31     2015-10-04   2015-09-03   Standard    MSN       Video      35
2015-08-31     2015-10-04   2015-09-04   Standard    MSN       Video      35
2015-08-31     2015-10-04   2015-09-05   Standard    MSN       Video      35
2015-08-31     2015-10-04   2015-09-06   Standard    MSN       Video      35
2015-08-31     2015-10-04   2015-09-07   Standard    MSN       Video      35

ETC……直到日期变量达到 2015-10-04,然后继续下一个复制

基本上每一行都会被复制 days in flight - 1 (因为已经存在的行可以占间隔中的一天,然后一个新列“日期”是填写该航班内的相关日期。因此,如果一行的开始日期和结束日期分别为 9/1 和 9/5,则会将 4 个重复的行附加到已经存在的行上,将创建一个新列(日期),并且原始行的航班开始日期和结束日期的日期序列将填写列值。

所有日期值都格式化为日期,飞行天数为数字,其余为因子。

编辑

针对重复的问题标记:

澄清一下,这不像被标记为重复的情况,因为我的问题并不是真正关注如何根据飞行天数进行复制(我已经知道如何做到这一点!),而是如何然后,我可以向该输出数据框添加列,并在相应的飞行期间按顺序插入日期。感谢您的提醒...

【问题讨论】:

  • 嘿@Jay,绝对不是,谢谢。我可能不应该包含有关复制行的所有内容,因为我了解如何使用expandRows(),但这个问题更多的是关于如何填写顺序日期列以配合该扩展

标签: r


【解决方案1】:

这是splitstackshapedplyr 的一种方式。使用 splitstackshape 包中的 expandRows(),您可以按照您的描述扩展数据框。然后,您想使用mutate() 添加日期序列。我所做的是通过Flight.StartFlight.End 的组合对数据进行分组,并使用seq() 为每个组创建一个日期序列。 first() 采用Flight.StartFlight.End 的第一个元素。这样,您可以创建您想要的序列。我希望这会对你有所帮助。

数据和代码

mydf <- data.frame(Flight.Start = as.Date(c("2015-09-01", "2015-09-10")),
                   Flight.End = as.Date(c("2015-09-03", "2015-09-15")),
                   Device = "Standard",
                   Creative = "Video",
                   Days.in.Flight = c(3, 6),
                   stringsAsFactors = FALSE)

#  Flight.Start Flight.End   Device Creative Days.in.Flight
#1   2015-09-01 2015-09-03 Standard    Video              3
#2   2015-09-10 2015-09-15 Standard    Video              6

library(splitstackshape)
library(dplyr)

expandRows(mydf, "Days.in.Flight", drop = FALSE) %>%
group_by(Flight.Start, Flight.End) %>%
mutate(Date = seq(first(Flight.Start),
                  first(Flight.End),
                  by = 1))

#  Flight.Start Flight.End   Device Creative Days.in.Flight       Date
#        (date)     (date)    (chr)    (chr)          (dbl)     (date)
#1   2015-09-01 2015-09-03 Standard    Video              3 2015-09-01
#2   2015-09-01 2015-09-03 Standard    Video              3 2015-09-02
#3   2015-09-01 2015-09-03 Standard    Video              3 2015-09-03
#4   2015-09-10 2015-09-15 Standard    Video              6 2015-09-10
#5   2015-09-10 2015-09-15 Standard    Video              6 2015-09-11
#6   2015-09-10 2015-09-15 Standard    Video              6 2015-09-12
#7   2015-09-10 2015-09-15 Standard    Video              6 2015-09-13
#8   2015-09-10 2015-09-15 Standard    Video              6 2015-09-14
#9   2015-09-10 2015-09-15 Standard    Video              6 2015-09-15

【讨论】:

    【解决方案2】:

    或使用data.table,我们将“data.frame”转换为“data.table”(setDT(mydf)),通过“Days.in.Flight”复制行序列,基于该索引,我们子集数据集 (.SD[rep(...),按“Flight.Start”和“Flight.End”分组,我们创建“日期”列。

    library(data.table)
    setDT(mydf)[, .SD[rep(1:.N, Days.in.Flight)]][, 
         Date:= seq(Flight.Start , Flight.End, by = '1 day'),
         by = .(Flight.Start, Flight.End)][]
    

    【讨论】:

      【解决方案3】:

      这是一种使用 base R 的方法:

      mydf <- data.frame(Flight.Start = as.Date(c("2015-09-01", "2015-09-10")),
                         Flight.End = as.Date(c("2015-09-03", "2015-09-15")),
                         Device = "Standard",
                         Creative = "Video",
                         Days.in.Flight = c(3, 6),
                         stringsAsFactors = FALSE)
      
      expanded <-mydf[rep(row.names(mydf), mydf$ Days.in.Flight), ]
      data.frame(expanded,Date=expanded$Flight.Start+(sequence(mydf$Days.in.Flight)-1))
      
      > data.frame(expanded,Date=expanded$Flight.Start+(sequence(mydf$Days.in.Flight)-1))
          Flight.Start Flight.End   Device Creative Days.in.Flight       Date
      1     2015-09-01 2015-09-03 Standard    Video              3 2015-09-01
      1.1   2015-09-01 2015-09-03 Standard    Video              3 2015-09-02
      1.2   2015-09-01 2015-09-03 Standard    Video              3 2015-09-03
      2     2015-09-10 2015-09-15 Standard    Video              6 2015-09-10
      2.1   2015-09-10 2015-09-15 Standard    Video              6 2015-09-11
      2.2   2015-09-10 2015-09-15 Standard    Video              6 2015-09-12
      2.3   2015-09-10 2015-09-15 Standard    Video              6 2015-09-13
      2.4   2015-09-10 2015-09-15 Standard    Video              6 2015-09-14
      2.5   2015-09-10 2015-09-15 Standard    Video              6 2015-09-15
      

      【讨论】:

        【解决方案4】:

        使用tidyversedplyrtidyrpurrr 的另一种方法。

        library(dplyr, quietly = TRUE, warn.conflicts = FALSE)
        
        mydf <- data.frame(Flight.Start = as.Date(c("2015-09-01", "2015-09-10")),
                           Flight.End = as.Date(c("2015-09-03", "2015-09-15")),
                           Device = "Standard",
                           Creative = "Video",
                           Days.in.Flight = c(3, 6),
                           stringsAsFactors = FALSE)
        
        
        mydf %>% 
          mutate(id = row_number()) %>% 
          group_by(id) %>% 
          tidyr::nest() %>% 
          mutate(
            Date = purrr::map(
              data, ~ seq(.x$Flight.Start, .x$Flight.End, by = "1 day")
            )) %>% 
          tidyr::unnest(c(data, Date))
        #> # A tibble: 9 x 7
        #> # Groups:   id [2]
        #>      id Flight.Start Flight.End Device   Creative Days.in.Flight Date      
        #>   <int> <date>       <date>     <chr>    <chr>             <dbl> <date>    
        #> 1     1 2015-09-01   2015-09-03 Standard Video                 3 2015-09-01
        #> 2     1 2015-09-01   2015-09-03 Standard Video                 3 2015-09-02
        #> 3     1 2015-09-01   2015-09-03 Standard Video                 3 2015-09-03
        #> 4     2 2015-09-10   2015-09-15 Standard Video                 6 2015-09-10
        #> 5     2 2015-09-10   2015-09-15 Standard Video                 6 2015-09-11
        #> 6     2 2015-09-10   2015-09-15 Standard Video                 6 2015-09-12
        #> 7     2 2015-09-10   2015-09-15 Standard Video                 6 2015-09-13
        #> 8     2 2015-09-10   2015-09-15 Standard Video                 6 2015-09-14
        #> 9     2 2015-09-10   2015-09-15 Standard Video                 6 2015-09-15
        

        reprex package (v2.0.1) 于 2022-02-21 创建

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-17
          • 1970-01-01
          • 2023-02-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多