【问题标题】:Select observations by date per ID每个 ID 按日期选择观察
【发布时间】:2022-01-03 05:51:00
【问题描述】:

我想按各个时间范围选择观察结果 - 我的模拟数据可以解释我需要什么:

有两个数据框:

  • event_data:包含在 某个日期。每个事件都是一个新的行,但是一个单独的 (由“event_person_id”标识的也可能经历不止一个 事件(可能是 2、3、4、5...)。
  • visit_data:包含与个人的所有个人联系。每一个 访问被分配给个人(“visit_person_id”)并具有 自己的访问日期。访问次数远多于活动。

Visit_data 最终包含的数据比我需要的多,因为我只想选择 visit_data 中发生在 "event_date" 加上两年之间的时间范围内的那些行

例如: Person_id 1 有两个事件 - 第一个在 2014 年 3 月 21 日,第二个在 2018 年 8 月 8 日,所以我想只选择 visit_data 中日期在 2014 年 3 月 21 日之间的那些行2016 年 3 月 21 日以及 2018 年 8 月 8 日至 2020 年 8 月 8 日之间。

我的想法是通过 person_id 加入 event_data 和 visit_data - 所以我有一个包含 visit_date 和 event_date 的新数据框,然后我可以选择相关信息,但我的方法并不完全正确(随机?)将第一个或第二个 event_date 分配给访问行 fe person_id 5 在 1988-12-15 进行了一次访问,但 event_date 是 2019-09-03 而不是 1988-03-04,因此此访问被忽略,因为 2019 不在1988 年到 1990 年。

如果我加入表格的想法完全错误,或者如果有更聪明的方法,我想学习这个更好的方法!

这是我的代码:

library(dplyr)
library(lubridate)

set.seed(123)

event_data <- data.frame(event_person_id = seq(1, 100, 1),
                         event_date = sample(seq(as.Date('1980/01/01'), as.Date('2010/12/31'), by="day"), 100),
                         age = round(runif(100, min = 1, max = 80)), 
                         bmi = round(runif(100, min = 19, max = 30)), 
                         amount = round(runif(100, min = 10, max = 10000)), 
                         stringsAsFactors = FALSE)

event_data2 <- data.frame(event_person_id = seq(1, 10, 1),
                         event_date = sample(seq(as.Date('2011/01/01'), as.Date('2020/12/31'), by="day"), 10),
                         age = round(runif(10, min = 1, max = 80)), 
                         bmi = round(runif(10, min = 19, max = 30)), 
                         amount = round(runif(10, min = 10, max = 10000)), 
                         stringsAsFactors = FALSE)

event_data_total <- rbind(event_data, event_data2)

visit_data <- data.frame(visit_person_id = round(runif(10000, min = 1, max = 100)),
                         visit_id = seq(1, 10000, 1),
                         visit_date = sample(seq(as.Date('1980/01/01'), as.Date('2020/12/31'), by="day"), 10000),
                         var1 = round(runif(10000, min = 1, max = 500)), 
                         var2 = round(runif(10000, min = 1, max = 1000)), 
                         var3 = round(runif(10000, min = 1, max = 9000)), 
                         stringsAsFactors = FALSE)

data_joined <-
  dplyr::inner_join(visit_data, event_data_total, by = c('visit_person_id' = 'event_person_id')) %>% 
  arrange(visit_date)

data_joined_final <- data_joined %>%
  filter(visit_date > event_date & visit_date < (event_date %m+% years(2)))

我真的很感谢你的帮助:)

【问题讨论】:

    标签: r date


    【解决方案1】:

    在帮助方面相当新,所以请怜悯;)但据我了解,解决方案可能来自“data.table”“foverlaps”。通过重叠日期和 ID 连接。我不能 100% 确定您希望最终数据的准确程度,但这里有一个建议,您可以根据自己的具体需要进行修改。

    library(dplyr)
    library(lubridate)
    library(data.table)
    
    
    set.seed(123)
    
    event_data <- data.frame(event_person_id = seq(1, 100, 1),
                             event_date = sample(seq(as.Date('1980/01/01'), as.Date('2010/12/31'), by="day"), 100),
                             age = round(runif(100, min = 1, max = 80)), 
                             bmi = round(runif(100, min = 19, max = 30)), 
                             amount = round(runif(100, min = 10, max = 10000)), 
                             stringsAsFactors = FALSE)
    
    event_data2 <- data.frame(event_person_id = seq(1, 10, 1),
                              event_date = sample(seq(as.Date('2011/01/01'), as.Date('2020/12/31'), by="day"), 10),
                              age = round(runif(10, min = 1, max = 80)), 
                              bmi = round(runif(10, min = 19, max = 30)), 
                              amount = round(runif(10, min = 10, max = 10000)), 
                              stringsAsFactors = FALSE)
    
    event_data_total <- rbind(event_data, event_data2)
    
    visit_data <- data.frame(visit_person_id = round(runif(10000, min = 1, max = 100)),
                             visit_id = seq(1, 10000, 1),
                             visit_date = sample(seq(as.Date('1980/01/01'), as.Date('2020/12/31'), by="day"), 10000),
                             var1 = round(runif(10000, min = 1, max = 500)), 
                             var2 = round(runif(10000, min = 1, max = 1000)), 
                             var3 = round(runif(10000, min = 1, max = 9000)), 
                             stringsAsFactors = FALSE)
    
    
    #create the end dates + 2 years
    event_data_total$end_date <- event_data_total$event_date + years(2)
    
    #set as data.table
    DT1 <- data.table(visit_data)
    DT2 <- data.table(event_data_total)
    
    #set joining keys
    setkey(DT2, event_person_id, event_date, end_date)
    
    #create dublicate columns with the same names, used for foverlaps
    DT1[, c("event_date", "end_date") := visit_date] 
    DT1[, c("event_person_id") := visit_person_id] 
    
    #join data
    data_joined<-foverlaps(DT1, DT2)
    
    # now you should be able to sort it with e.g.
    dat <- data_joined[complete.cases(data_joined), ]
    

    【讨论】:

    • 嗨!很抱歉我的回复很晚 - 我无法更早地测试你的解决方案......它有效 - 非常感谢你:)
    • 没问题,很高兴它有用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多