【问题标题】:How to align date based on the next row in r?如何根据 r 中的下一行对齐日期?
【发布时间】:2021-10-07 16:33:39
【问题描述】:

我有一个类似于我们在下面看到的数据。实际数据中,1个PATIENT_ID可能有2行以上。

df
# PATIENT_ID DRUG_CLASS start      end        duration 
# <dbl>      <chr>      <date>     <date>     <drtn>   
#          1 SU         2014-03-05 2016-08-04  883 days
#          1 DPP4       2016-07-22 2016-08-26   35 days
#          2 SU         2014-01-07 2017-06-23 1263 days
#          2 DPP4       2015-03-04 2017-12-27 1029 days
#          3 SU         2014-01-09 2014-12-05  330 days
#          3 SU         2015-01-08 2016-01-07  364 days

我想做的是为每个患者取第一行,但如果间隔与下一个间隔重叠,则在下一行中,我们将end 日期作为start 日期后续行- 1。示例:

  1. 对于第一个患者,由于end 日期大于下一行的start 日期,即"2016-08-04" > "2016-07-22",那么新的end 日期应为"2016-07-21"
  2. 同样,对于第二位患者,我们将新的end 日期设为"2015-03-04" - 1 = "2015-03-03"
  3. 对于最后一位患者,由于没有重叠,所以按原样取第一行

最终数据:

df
# PATIENT_ID DRUG_CLASS start      end        
# <dbl>      <chr>      <date>     <date>        
#          1 SU         2014-03-05 2016-07-21  
#          2 SU         2014-01-07 2015-03-03 
#          3 SU         2014-01-09 2014-12-05

代码:

df <- structure(list(PATIENT_ID = c(1, 1, 2, 2, 3, 3), DRUG_CLASS = c("SU", 
"DPP4", "SU", "DPP4", "SU", "SU"), start = structure(c(16134, 
17004, 16077, 16498, 16079, 16443), class = "Date"), end = structure(c(17017, 
17039, 17340, 17527, 16409, 16807), class = "Date"), duration = structure(c(883, 
35, 1263, 1029, 330, 364), class = "difftime", units = "days")), row.names = c(NA, 
-6L), class = c("tbl_df", "tbl", "data.frame"))

【问题讨论】:

    标签: r dplyr lubridate


    【解决方案1】:

    非常适合tidyverse

    library(tidyverse)
    df %>% 
      group_by(PATIENT_ID) %>% 
      summarise(DRUG_CLASS = toString(unique(DRUG_CLASS)),
                end= if_else(first(end) > last(start) , max(start)-1, min(end)),
                start = first(start)) %>% 
      select(1:2, start, end)
    # A tibble: 3 x 4
      PATIENT_ID DRUG_CLASS start      end       
           <dbl> <chr>      <date>     <date>    
    1          1 SU, DPP4   2014-03-05 2016-07-21
    2          2 SU, DPP4   2014-01-07 2015-03-03
    3          3 SU         2014-01-09 2014-12-05
    

    【讨论】:

      【解决方案2】:

      你可以使用

      library(lubridate)
      library(dplyr)
      
      df %>% 
        group_by(PATIENT_ID) %>% 
        mutate(new_end = min(coalesce(lead(start), end) - 1, end)) %>% 
        slice_head(n = 1) %>% 
        select(PATIENT_ID, DRUG_CLASS, start, end = new_end) %>% 
        ungroup()
      

      返回

      # A tibble: 3 x 4
        PATIENT_ID DRUG_CLASS start      end       
             <dbl> <chr>      <date>     <date>    
      1          1 SU         2014-03-05 2016-07-21
      2          2 SU         2014-01-07 2015-03-03
      3          3 SU         2014-01-09 2014-12-05
      

      【讨论】:

        【解决方案3】:

        我只是仔细检查一下日期安排是否正常

        library(dplyr)
        library(lubridate)
        df %>%
          as_tibble() %>%
          arrange(PATIENT_ID, start) %>%
          group_by(PATIENT_ID) %>%
          mutate(
            x1 = lead(start, 1L, dmy("01/01/2999"))-1,
            end_new = if_else(end > x1, x1, end)
          ) %>%
          select(-x1)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-02-10
          • 1970-01-01
          • 1970-01-01
          • 2019-02-06
          • 2021-11-17
          • 2020-08-18
          • 1970-01-01
          相关资源
          最近更新 更多