每个 ID 按日期选择观察
Posted
技术标签:
【中文标题】每个 ID 按日期选择观察【英文标题】:Select observations by date per 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)))
我真的很感谢你的帮助:)
【问题讨论】:
【参考方案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), ]
【讨论】:
嗨!很抱歉我的回复很晚 - 我无法更早地测试你的解决方案......它有效 - 非常感谢你:) 没问题,很高兴它有用以上是关于每个 ID 按日期选择观察的主要内容,如果未能解决你的问题,请参考以下文章