R 每个受试者每X天仅计算一次事件(在不规则的时间序列中)

R 每个受试者每X天仅计算一次事件(在不规则的时间序列中),r,R,我有数据统计护理事件(如急诊室就诊)。诀窍是,我不能计算每一次访问,因为有时第二次或第三次访问实际上是对以前问题的后续。因此,我被指示使用30天的“清洁期”或“断电期”来计算就诊次数,这样,我会按患者(最小日期)查找第一个事件(就诊1),我计算该事件,然后应用规则,以便不计算第一个事件后30天内发生的任何就诊次数。在30天窗口结束后,我可以开始寻找第二次就诊(第2次就诊),计算第二次就诊的次数,然后再次应用30天断电(不计算第2次就诊后30天内发生的就诊次数)。。。清洗,冲洗,重复 我拼凑了一个

我有数据统计护理事件(如急诊室就诊)。诀窍是,我不能计算每一次访问,因为有时第二次或第三次访问实际上是对以前问题的后续。因此,我被指示使用30天的“清洁期”或“断电期”来计算就诊次数,这样,我会按患者(最小日期)查找第一个事件(就诊1),我计算该事件,然后应用规则,以便不计算第一个事件后30天内发生的任何就诊次数。在30天窗口结束后,我可以开始寻找第二次就诊(第2次就诊),计算第二次就诊的次数,然后再次应用30天断电(不计算第2次就诊后30天内发生的就诊次数)。。。清洗,冲洗,重复

我拼凑了一个非常草率的解决方案,需要很多保姆和手动检查步骤(见下文)。我必须相信有更好的办法。救命啊

data1 <- structure(list(ID = structure(c(2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 
3L, 4L, 4L, 4L, 4L, 4L), .Label = c("", "patient1", "patient2", 
"patient3"), class = "factor"), Date = structure(c(14610, 14610, 
14627, 14680, 14652, 14660, 14725, 15085, 15086, 14642, 14669, 
14732, 14747, 14749), class = "Date"), test = c(1L, 1L, 1L, 2L, 
1L, 1L, 2L, 3L, 3L, 1L, 1L, 2L, 2L, 2L)), .Names = c("ID", "Date", 
"test"), class = "data.frame", row.names = c(NA, 14L))

library(doBy) 
##     create a table of first events 
step1 <- summaryBy(Date~ID, data = data1, FUN=min) 
step1$Date30 <- step1$Date.min+30                                     
step2 <- merge(data1, step1, by.x="ID", by.y="ID") 
##     use an ifelse to essentially remove any events that shouldn't be counted 
step2$event <- ifelse(as.numeric(step2$Date) >= step2$Date.min & as.numeric(step2$Date) <= step2$Date30, 0, 1)
##     basically repeat steps above until I dont capture any more events
##  there just has to be a better way
data3 <- step2[step2$event==1,] 
data3<- data3[,1:3] 
step3 <- summaryBy(Date~ID, data = data3, FUN=min) 
step3$Date30 <- step3$Date.min+30 
step4 <- merge(data3, step3, by.x="ID", by.y="ID") 
step4$event <- ifelse(as.numeric(step4$Date) >= step4$Date.min & as.numeric(step4$Date) <= step4$Date30, 0, 1)
data4 <- step4[step4$event==1,]
data4<- data4[,1:3]
step5 <- summaryBy(Date~ID, data = data4, FUN=min)
step5$Date30 <- step5$Date.min+30
##     then I rbind the "keepers" 
##     in this case steps 1 and 3 above 
final <- rbind(step1,step3, step5) 
##     then reformat 
final <- final[,1:2] 
final$Date.min <- as.Date(final$Date.min,origin="1970-01-01") 
##     again, extremely clumsy, but it works...  HELP! :)

data1由于这种操作并不简单且容易出错,
我将编写一个单独的函数来丢弃断电期间的事件。
函数包含一个循环,
基本上就是你用手做的,
直到无事可做

blackout <- function(dates, period=30) {
  dates <- sort(dates)
  while( TRUE ) {
    spell <- as.numeric(diff(dates)) <= period
    if(!any(spell)) { return(dates) }
    i <- which(spell)[1] + 1
    dates <- dates[-i]
  }
}

# Tests
stopifnot( 
  length(
    blackout( seq.Date(Sys.Date(), Sys.Date()+50, by=1) )
  ) == 2
)
stopifnot( 
  length(
    blackout( seq.Date(Sys.Date(), by=31, length=5) )
  ) == 5
)

此解决方案是无循环的,只使用基R。它生成一个逻辑向量
ok
,选择可接受的
data1

ave
分别对每个患者运行指定的匿名功能

我们定义了一个状态向量,由当前日期和不考虑其他日期的时段开始组成。每个日期由
表示为数字(x)
,其中
x
是日期<代码>步骤
获取状态向量和当前日期,并更新状态向量
Reduce
在数据上运行它,然后我们只获取最小日期和当前日期相同且当前日期不重复的结果

step <- function(init, curdate) {
    c(curdate, if (curdate > init[2] + 30) curdate else init[2])
}

ok <- !!ave(as.numeric(data1$Date), paste(data1$ID), FUN = function(d) {
    x <- do.call("rbind", Reduce(step, d, c(-Inf, 0), acc = TRUE))
    x[-1,1] == x[-1,2] & !duplicated(x[-1,1])
})

data1[ok, ]
step init[2]+30)curdate else init[2])
}
好的,怎么样

do.call('rbind', lapply(split(data1, factor(data1$ID)), function(x) (x <- x[order(x$Date),])[c(T, diff(x$Date) > 30),]))
do.call('rbind',lappy(拆分(data1,factor(data1$ID)),函数(x)(x30),]))
do.call('rbind', lapply(split(data1, factor(data1$ID)), function(x) (x <- x[order(x$Date),])[c(T, diff(x$Date) > 30),]))