首页 > 解决方案 > 查找多个时间范围的最近时间

问题描述

我正在尝试创建一个程序,在最多 900 天 (1-30,31-60,61-90......871-900) 的 30 天范围内选择最近的一天。我正在使用R版本 3.3.3。

这是我拥有的数据集的示例:

    have <- structure(list(id = c(1L, 1L, 1L, 2L, 2L, 3L, 3L, 4L, 4L, 4L, 
5L, 5L, 6L, 6L, 7L, 7L, 7L, 7L, 8L, 8L, 8L, 8L, 8L, 9L, 9L, 9L, 
9L, 9L, 9L, 9L, 9L, 9L), time.to.first = c(0L, 78L, 293L, 0L, 
63L, 0L, 89L, 0L, 11L, 27L, 0L, 28L, 0L, 29L, 0L, 31L, 381L, 
778L, 0L, 28L, 69L, 96L, 466L, 0L, 28L, 56L, 98L, 154L, 220L, 
294L, 395L, 507L), visit = c(1L, 2L, 3L, 1L, 2L, 1L, 2L, 1L, 
2L, 3L, 1L, 2L, 1L, 2L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 5L, 1L, 
2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L)), .Names = c("id", "time.to.first", 
"visit"), row.names = c(NA, 32L), class = "data.frame")

这是我想要的:

want <- structure(list(id = c(1L, 1L, 1L, 2L, 2L, 3L, 3L, 4L, 4L, 4L, 
5L, 5L, 6L, 6L, 7L, 7L, 7L, 7L, 8L, 8L, 8L, 8L, 8L, 9L, 9L, 9L, 
9L, 9L, 9L, 9L, 9L, 9L), time.to.first = c(0L, 78L, 293L, 0L, 
63L, 0L, 89L, 0L, 11L, 27L, 0L, 28L, 0L, 29L, 0L, 31L, 381L, 
778L, 0L, 28L, 69L, 96L, 466L, 0L, 28L, 56L, 98L, 154L, 220L, 
294L, 395L, 507L), visit = c(1L, 2L, 3L, 1L, 2L, 1L, 2L, 1L, 
2L, 3L, 1L, 2L, 1L, 2L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 5L, 1L, 
2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L), time.window = structure(c(1L, 
11L, 5L, 1L, 11L, 1L, 11L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 6L, 
7L, 12L, 1L, 2L, 11L, 13L, 9L, 1L, 2L, 6L, 13L, 3L, 4L, 5L, 8L, 
10L), .Label = c("", "1-30", "151-180", "211-240", "271-300", 
"31-60", "361-390", "391-420", "451-480", "481-510", "61-90", 
"751-780", "91-120"), class = "factor")), .Names = c("id", "time.to.first", 
"visit", "time.window"), row.names = c(NA, 32L), class = "data.frame")

我能够弄清楚如何使用一系列ifelse语句和第filter一个left_join日期范围(1-30 天)创建日期范围:

x <- 1
y <- 30

df <- have %>% group_by(id) %>% 
               mutate(flag  = ifelse(time.to.first >= x & time.to.first <= y,max(visit),""),
                      flag2 = ifelse(flag  == max(flag)  & flag != "",1,"")) %>%
                      filter(flag > 0 & flag2 == 1) %>%
                      filter(visit == max(visit)) %>%
                      mutate(time = paste(x,"-", y, sep = "")) %>% 
                      dplyr::select(time, id, visit) %>%
                      left_join(have, ., by = c("id","visit"))

x我在想我可以对and变量使用双重嵌套的 for 循环,y以创建一个可以执行其余日期范围的程序,但我知道嵌套循环可能不是解决此问题的最有效方法。

我试图想办法让程序更健壮一点,这样我就可以改变窗口的时间(从 30 天到 90,180,360 等......),但我不知道如何处理这个问题。

我不想要为我编写的代码,但会喜欢你认为可能有用的函数或示例的想法。我一直很难找到此类程序的更多信息,因此任何其他链接都会有所帮助!

标签: rtimedplyr

解决方案


使用从@Frank 截取的代码,我可以执行以下操作:

want1 <- have %>% mutate(x = as.character(cut(time.to.first, seq(0, ceiling(max(time.to.first)/30)*30, by=30)))) %>% group_by(id,x) %>%  filter(visit == max(visit)) %>% mutate(y = x) %>% ungroup()

在最后一步中,我取出了在特定时间范围内选择了不止一次访问的情况,并进行了最近一次访问(对应于最接近时间范围顶部的日期)。我现在要做的就是一个简单的str_extract_all,也许是一个 grepl 来完成时间范围代码。


推荐阅读