我有一个数据集,随着时间的推移,该数据集对多个人进行了重复测量。看起来像这样:
ID Time Event
1 Jan 1 2012, 4pm Abx
1 Jan 2 2012, 2pm Test
1 Jan 26 2012 3 pm Test
1 Jan 29 2012 10 pm Abx
1 Jan 30 2012, 3 pm Test
1 Jan 5 2012 3 pm Test
2 Jan 1 2012, 4pm Abx
2 Jan 2 2012, 2pm Test
2 Jan 26 2012 3 pm Test
数据集当前基于事件。稍后将其过滤下来以进行测试。我需要做的是在测试的特定时间范围内发生某些事件(在这种情况下为Abx)时,将新变量设置为1。因此,如果事件“ Abx”在Test事件发生48小时之内发生,则新变量应等于1。否则,它应等于0。 我希望产生这样的东西:
ID Time Event New_variable
1 Jan 1 2012, 4pm Abx 1
1 Jan 2 2012, 2pm Test 1
1 Jan 26 2012 3 pm Test 0
1 Jan 29 2012 10 pm Abx 1
1 Jan 30 2012, 3 pm Test 1
1 Jan 5 2012 3 pm Test 0
2 Jan 1 2012, 4pm Abx 1
2 Jan 2 2012, 2pm Test 1
2 Jan 26 2012 3 pm Test 0
我知道我可以结合使用Dplyr mutate函数和ifelse语句来解决此问题,并且如果我只是想在发生抗生素事件时创建一个读取为“ 1”的变量,我可以这样做: / p>
test %>%
mutate(New_variable = ifelse(Event == 'Abx', 1, 0)) -> test2
但是我不知道如何计算时间,以便在Abx事件的48小时内测试事件= 1。我也不确定如何确保仅在同一ID中应用该条件。我该怎么办?
感谢您的帮助!
更新:非常感谢您的建议! 我将对数据进行尝试,但我认为它们会起作用。如果没有,我会很快回来。成功!我还修改了建议的辅助函数,以包括其他选项(适用于多种类型的Abx):
abxRows <- type == "Abx" | type == "Abx2"
答案 0 :(得分:0)
所以我没有您的数据的副本,所以我不确定您的日期是多少……
我建议您使用as.POSIXct(Time, format="%b %d %Y, %I%p")
将日期转换为正确的格式,有关该格式的更多信息,请查阅?strptime
,但我认为这对您的专栏来说是正确的。
如果我们假设您的数据框是这样的...我知道我已经更改了部分内容,但这只是为了简单起见
df <- data.frame(ID = c(rep(1,6),rep(2,3)),
Time=c(seq(from=start, by=interval*6840, to=end)[1:6],seq(from=start, by=interval*6840, to=end)[1:3]),
Event = rep(c("Abs","Test","Test"),3))
这看起来像这样
ID Time Event
1 1 2012-01-01 00:00:00 Abs
2 1 2012-01-05 18:00:00 Test
3 1 2012-01-10 12:00:00 Test
4 1 2012-01-15 06:00:00 Abs
5 1 2012-01-20 00:00:00 Test
6 1 2012-01-24 18:00:00 Test
7 2 2012-01-01 00:00:00 Abs
8 2 2012-01-05 18:00:00 Test
9 2 2012-01-10 12:00:00 Test
因此,您可以使用以下代码测试Test
到48小时内是否Abs
落入
df[which(df$Event=="Test"),]$Time %in% unlist(Map(`:`, df[which(df$Event=="Abs"),]$Time-48*60*60, df[which(df$Event=="Abs"),]$Time+48*60*60))
因此这将对所有人返回FALSE,但这是因为综合数据的时间步长较大。
要打开包装...
df[which(df$Event=="Test"),]$Time
给出测试时间
%in%
说的是在此之后的一组值中寻找在此之前的内容。
所以它是:unlist(Map(`:`, df[which(df$Event=="Abs"),]$Time-48*60*60, df[which(df$Event=="Abs"),]$Time+48*60*60))
这将为每个Abs
创建一个+/- 48小时的日期列表。加或减48小时,像POSIXct这样的对象在几秒钟内完成,因此48*60*60
答案 1 :(得分:0)
在提供的数据中,我添加了两个不应该是“ Abx”事件(即,一个不在48小时内的事件,另一个不在与48小时内的测试属于同一组的事件)。 / p>
library(dplyr)
library(lubridate)
library(purrr)
eventData <-
data.frame(stringsAsFactors = FALSE,
ID = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1),
Time = c("Jan 1 2012 4 pm", "Jan 2 2012, 2pm",
"Jan 26 2012 3 pm", "Jan 29 2012 10 pm",
"Jan 30 2012 3 pm", "Jan 5 2012 3 pm",
"Jan 1 2012 4 pm", "Jan 2 2012, 2pm",
"Jan 26 2012 3 pm", "Feb 12 2012 1pm",
"Jan 16 2012 3 pm", "Jan 16 2012 1 pm"),
Event = c("Abx", "Test", "Test", "Abx", "Test", "Test",
"Abx", "Test", "Test", "Abx", "Abx", "Test")
) %>%
mutate(Time = mdy_h(Time),
window = if_else(Event == "Test",
interval(Time - hours(48), Time + hours(48)),
interval(NA, NA))
)
首先,您要确保Time
列是时间格式。然后创建一个lubridate
时间间隔类的列,该列围绕“测试”事件创建一个48小时的窗口。
定义帮助程序功能,该功能将检查事件是否在窗口内发生。
chkFun <- function(eventTime, intervals, grp, type){
abxRows <- type == "Abx"
testRows <- !abxRows
hits <- map2_lgl(eventTime, grp,
~any(.x %within% intervals[grp %in% .y], na.rm = TRUE)) &
abxRows
testHits <- map_lgl(which(testRows),
~any(eventTime[abxRows & (grp[.x] == grp)] %within%
intervals[.x]))
hits[testRows] <- testHits
as.integer(hits)
}
此功能首先通过并测试是否在间隔内发生“ Abx”事件。然后,它确定哪些“测试”行的间隔包含一个“ Abx”事件。该函数将这些强制转换的组合返回为整数。
最后,只需在helper函数中使用mutate语句,然后删除窗口列
eventData %>%
mutate(New_variable = chkFun(Time, window, ID, Event)) %>%
select(-window)
或者,辅助函数可以仅将data.frame作为参数并采用列名。但是,在上面的表格中,如果您首先在脚本中定义它,那么它也可以用在eventData
结果:
#> ID Time Event New_variable
#> 1 1 2012-01-01 16:00:00 Abx 1
#> 2 1 2012-01-02 14:00:00 Test 1
#> 3 1 2012-01-26 15:00:00 Test 0
#> 4 1 2012-01-29 22:00:00 Abx 1
#> 5 1 2012-01-30 15:00:00 Test 1
#> 6 1 2012-01-05 15:00:00 Test 0
#> 7 2 2012-01-01 16:00:00 Abx 1
#> 8 2 2012-01-02 14:00:00 Test 1
#> 9 2 2012-01-26 15:00:00 Test 0
#> 10 2 2012-02-12 13:00:00 Abx 0
#> 11 2 2012-01-16 15:00:00 Abx 0
#> 12 1 2012-01-16 13:00:00 Test 0