代码之家  ›  专栏  ›  技术社区  ›  ForEverNewbie

筛选时间段在另一行时间段内的行

  •  0
  • ForEverNewbie  · 技术社区  · 11 月前

    我有一个类似于以下最小示例的数据集:

       Category  date_in                date_out
       KA        2018-09-05            2018-10-08                   
       KA        2018-09-05            2018-09-18                         
       KA        2018-09-18            2018-09-24                    
       KB        2018-09-24            2018-10-08
    

    使用dplyr,我如何在每个类别中消除周期(date_in-date_out)在同一类别的另一行的周期内的行?在上面的例子中,经过过滤后,我们会

       Category  date_in                date_out
       KA        2018-09-05            2018-10-08                                   
       KB        2018-09-24            2018-10-08
    
    2 回复  |  直到 11 月前
        1
  •  2
  •   Allan Cameron    11 月前

    在每组中,取每一行,检查其开始日期是否大于或等于组中任何其他行的开始日期。然后检查其结束日期是否小于组中任何其他行的结束日期。如果 二者都 这些条件是 TRUE 对于此行,与相比 any 在其他行中,则应过滤掉这一行。

    一种步行方式是:

    library(tidyverse)
    
    df %>%
      filter(df %>%
        mutate(across(contains('date'), as.Date)) %>%
        group_split(Category) %>%
        map(~ sapply(seq(nrow(.x)), function(i) {
                !any(.x$date_in[i] >= .x$date_in[-i] & 
                     .x$date_out[i] <= .x$date_out[-i])
          })) %>%
        unlist())
    #>   Category    date_in   date_out
    #> 1       KA 2018-09-05 2018-10-08
    #> 2       KB 2018-09-24 2018-10-08
    

    上述示例中使用的数据取自问题并可复制

    df <- structure(list(Category = c("KA", "KA", "KA", "KB"), 
                         date_in = c("2018-09-05", "2018-09-05", "2018-09-18", 
                                     "2018-09-24"), 
                         date_out = c("2018-10-08", "2018-09-18", "2018-09-24", 
                                      "2018-10-08")), 
                    class = "data.frame", row.names = c(NA, -4L))
    
        2
  •  0
  •   mediode    11 月前

    我不太喜欢dplyr,但我可以建议的解决方案如下:

    d <- data.frame(a = c('KA','KA','KA','KB'), 
               date_in=as.Date(c('2018-09-05','2018-09-05','2018-09-18','2018-09-24')),
               date_out=as.Date(c('2018-10-08','2018-09-18','2018-09-24','2018-10-08')))
    
    library(dplyr)
    d2 <- d %>% group_by(a) %>% mutate(date_in = min(date_in)) %>% mutate(date_out = max(date_out))  
    d2 <- d2[!duplicated(d2),]
    
    print(d2)
    
    # A tibble: 2 × 3
    # Groups:   a [2]
      a     date_in    date_out  
      <chr> <date>     <date>    
    1 KA    2018-09-05 2018-10-08
    2 KB    2018-09-24 2018-10-08