【问题标题】:Creating an statement to check multiple dates between a start and end date创建语句以检查开始日期和结束日期之间的多个日期
【发布时间】:2021-07-07 19:01:29
【问题描述】:

我在 R 中有一个这样的数据框:

Start date End date Date 1 Date 2 Date 3 Date 4
11/12/2018 29/11/2019 08/03/2021 NA NA NA
07/03/2018 24/04/2019 08/03/2021 12/09/2016 NA NA
04/06/2018 23/04/2019 08/03/2021 02/10/2017 05/10/2018 NA
26/07/2018 29/08/2019 08/03/2021 03/08/2015 02/10/2017 23/01/2017

我想在 R 中创建一个新列:如果日期 1、日期 2、日期 3 或日期 4 介于开始日期和结束日期之间,则应返回 1,否则返回 0,如下表所示:

Start date End date Date 1 Date 2 Date 3 Date 4 Change
11/12/2018 29/11/2019 08/03/2021 NA NA NA 0
07/03/2018 24/04/2019 08/03/2021 12/09/2016 NA NA 0
04/06/2018 23/04/2019 08/03/2021 02/10/2017 05/10/2018 NA 1
26/07/2018 29/08/2019 08/03/2021 03/08/2015 02/10/2017 23/01/2017 0

有人对如何解决这个问题有建议吗?谢谢你:)

【问题讨论】:

  • 请将您的数据发布到命令dput(your_dataframe) 的输出中,以便我们更轻松地访问您的数据。还包括您尝试过的任何代码和/或您遇到的错误。

标签: r dataframe date if-statement


【解决方案1】:

如果您可以发布我们可以直接运行的代码/数据,人们会更容易帮助您。最简单的方法是使用一个名为dput 的便捷 R 函数,该函数生成指令以精确地重新创建任何 R 对象。因此,您可以运行dput(MY_DATA),或者如果您的数据远大于展示您的问题所需的数据,请使用dput(head(MY_DATA)) 获取前六行,并将其输出粘贴到您的问题中。 </PSA>


这是生成示例数据的代码:

my_data <- data.frame(
  stringsAsFactors = FALSE,
        Start.date = c("11/12/2018", "07/03/2018", "04/06/2018", "26/07/2018"),
          End.date = c("29/11/2019", "24/04/2019", "23/04/2019", "29/08/2019"),
            Date.1 = c("08/03/2021", "08/03/2021", "08/03/2021", "08/03/2021"),
            Date.2 = c(NA, "12/09/2016", "02/10/2017", "03/08/2015"),
            Date.3 = c(NA, NA, "05/10/2018", "02/10/2017"),
            Date.4 = c(NA, NA, NA, "23/01/2017")
)

这是一种 tidyverse 方法,首先使用 lubridate::dmy 将您的日/月/年日期转换为 R 日期类型的数据,然后将 Date.1 到 Date.4 中的每个日期与您的开始日期进行比较,最后显示如果有任何 1(在范围内)。

library(dplyr); library(lubridate)
my_data %>%
  mutate(across(.fns = ~dmy(.x))) %>%
  mutate(across(.cols = starts_with("Date"),
                .fns = ~coalesce(.x >= Start.date & .x <= End.date, FALSE)*1)) %>%
  mutate(Change = pmax(Date.1, Date.2, Date.3, Date.4))

coalesce(..., FALSE) 在这里用于将 NA 视为 FALSE。

(...)*1 将 TRUE/FALSE 转换为 1/0。

pmax(...) 获取最大的 1/0,即“是否有任何 1?”


编辑:保留日期列不变的替代方法:

my_data %>%
  mutate(across(.fns = ~dmy(.x))) %>%
  mutate(across(.cols = starts_with("Date"), 
                .names = "Check_{.col}",
                .fns = ~coalesce(.x >= Start.date & .x <= End.date, FALSE)*1)) %>%
  rowwise() %>%
  mutate(Change = max(c_across(starts_with("Check")))) %>%
  select(-starts_with("Check"))

  Start.date End.date   Date.1     Date.2     Date.3     Date.4     Change
  <date>     <date>     <date>     <date>     <date>     <date>      <dbl>
1 2018-12-11 2019-11-29 2021-03-08 NA         NA         NA              0
2 2018-03-07 2019-04-24 2021-03-08 2016-09-12 NA         NA              0
3 2018-06-04 2019-04-23 2021-03-08 2017-10-02 2018-10-05 NA              1
4 2018-07-26 2019-08-29 2021-03-08 2015-08-03 2017-10-02 2017-01-23      0

【讨论】:

    【解决方案2】:
    library(tidyverse)
    library(lubridate)
    
    df <- read.table(textConnection("start_date;end_date;date_1;date_2;date_3;date_4
    11/12/2018;29/11/2019;08/03/2021;NA;NA;NA
    07/03/2018;24/04/2019;08/03/2021;12/09/2016;NA;NA
    04/06/2018;23/04/2019;08/03/2021;02/10/2017;05/10/2018;NA
    26/07/2018;29/08/2019;08/03/2021;03/08/2015;02/10/2017;23/01/2017"),
                     sep=";",
                     header = TRUE)
    df %>%
      mutate(
        across(everything(), lubridate::dmy),
        change = ((date_1 > start_date & date_1 < end_date) |
                    (date_2 > start_date & date_2 < end_date) |
                    (date_3 > start_date & date_3 < end_date)
        ) %>%
          coalesce(FALSE) %>%
          as.integer()
      )
    #>   start_date   end_date     date_1     date_2     date_3     date_4 change
    #> 1 2018-12-11 2019-11-29 2021-03-08       <NA>       <NA>       <NA>      0
    #> 2 2018-03-07 2019-04-24 2021-03-08 2016-09-12       <NA>       <NA>      0
    #> 3 2018-06-04 2019-04-23 2021-03-08 2017-10-02 2018-10-05       <NA>      1
    #> 4 2018-07-26 2019-08-29 2021-03-08 2015-08-03 2017-10-02 2017-01-23      0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多