【问题标题】:Find if a date overlaps between multiple pairs of vectorised dates查找日期是否在多对矢量化日期之间重叠
【发布时间】:2021-04-21 16:06:16
【问题描述】:

我试图找出在我的数据集中很宽的多对日期之间是否存在一个日期 - 我在这里给出的长度只是一个例子,最终的数字可能更大或更小。不确定这是否是最明智的选择,但长期工作似乎不起作用,这也是在 SPSS 中处理重叠日期和日期对的一种非常常见的方法,您可以在此处对多个变量进行数字化日期和它通过每个编号的“集合”来给你一个响应。

这是一个示例数据集:

  person   key_date 1_end_date 2_end_date 3_end_date 4_end_date 1_start_date 2_start_date 3_start_date 4_start_date
1      1 2019-09-30 2019-05-23 2019-09-30 2016-07-22       <NA>   2019-05-23   2019-09-30   2016-07-22         <NA>
2      2 2019-06-07 2019-05-16 2019-06-07       <NA>       <NA>   2019-05-16         <NA>         <NA>         <NA>
3      3 2020-03-09 2016-06-02 2019-08-09 2020-05-27 2020-02-12   2016-06-02   2019-08-09   2020-05-27   2020-03-09

test <- structure(list(person = 1:3, key_date = structure(c(18169, 18054,18330), class = "Date"), `1_end_date` = structure(c(18039, 18032,16954), class = "Date"), `2_end_date` = structure(c(18169, 18054,18117), class = "Date"), `3_end_date` = structure(c(17004, NA,18409), class = "Date"), `4_end_date` = structure(c(NA, NA, 18304), class = "Date"), `1_start_date` = structure(c(18039, 18032,16954), class = "Date"), `2_start_date` = structure(c(18169,NA, 18117), class = "Date"), `3_start_date` = structure(c(17004,NA, 18409), class = "Date"), `4_start_date` = structure(c(NA,NA, 18330), class = "Date")), row.names = c(NA, 3L), class = "data.frame") 

预期的输出将只是一个二进制标志,表示key_date 存在于任何一对start_dateend_date 之间。在给出的示例中,这意味着person 1 和 3。任何想法如何做到这一点?这真的低效吗?

【问题讨论】:

  • 为什么是人 3?请重新检查!
  • 是的,人 3 错了,我的错 - 道歉!

标签: r date dplyr


【解决方案1】:

tidyverse 接近

library(tidyverse)
result <- test %>% mutate(across(ends_with("end_date"), ~ 
                         key_date <= . & key_date >= get(str_replace(cur_column(), "end", "start")),
                       .names = '{.col}_flag')) %>%
  rowwise() %>%
  mutate(Flag1 = sum(c_across(ends_with("flag")), na.rm = T)) %>%
  ungroup() %>%
  select(-ends_with("flag"))

> result$Flag1
[1] 1 0 0

完整的输出看起来像

> result
# A tibble: 3 x 11
  person key_date   `1_end_date` `2_end_date` `3_end_date` `4_end_date` `1_start_date` `2_start_date` `3_start_date` `4_start_date` Flag1
   <int> <date>     <date>       <date>       <date>       <date>       <date>         <date>         <date>         <date>         <dbl>
1      1 2019-09-30 2019-05-23   2019-09-30   2016-07-22   NA           2019-05-23     2019-09-30     2016-07-22     NA                 1
2      2 2019-06-07 2019-05-16   2019-06-07   NA           NA           2019-05-16     NA             NA             NA                 0
3      3 2020-03-09 2016-06-02   2019-08-09   2020-05-27   2020-02-12   2016-06-02     2019-08-09     2020-05-27     2020-03-09         0

【讨论】:

  • 这是一个很棒的解决方案,而且比我以前的工作要快得多。我稍微改变了它,所以它被安置在~as.numeric而不是~ifelse。实际上,我还有其他非日期列使这一点复杂化,但调整这个get(str_replace(cur_column(), "end", "start") 真的很有用。谢谢!
  • 是的,as.numeric 是一种更好的方法。这取决于一个人习惯了。不过很高兴能帮上忙。
  • 即使as.numeric 也没有必要。当 keydate 位于两个组中时(如果可能),它会将 flag 转换为大于 1
  • 啊有趣。我希望在一个普通的mutate 命令中这个功能可以工作:你可以创建一个逻辑参数,它会创建一个布尔值,而不是必须将它包装在as.numeric
  • 有效!实际上在最后一步将布尔值包装成一个总和将其转换为数字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-27
相关资源
最近更新 更多