【发布时间】:2018-02-08 18:25:45
【问题描述】:
我希望将事件开始和结束日期的列表转换为状态向量,其中开始和结束之间的任何一天都是 1,外面是 0(例如 2,4 -> c(0, 1,1,1,0,0))
每个主题(由 id 键入)可能有多个开始和结束日期,在不同的行中,需要组合。
我有一个非常依赖 lapply 的解决方案(如果需要,我可以使用超级计算机,因此可以将它们切换到 mclapply),但我希望尽可能将事物矢量化,因为输入数据可能很大(~250MB)。
任何人都可以在这里找到减少任何步骤的途径吗?
require(data.table)
#The days that will be assessed for state
period = as.integer(1:8)
#Indices for days (they are not necessarily sequential)
dayInds = as.integer(1:length(period))
#Events for same ID will never overlap
dt = data.table(id = c("a","a","b","c","d","d","e"),
start = c(1,6,3,3,3,5,5),
end = c(4,7,6,7,4,6,5))
# setkeyv(dt,colnames(dt))
setkeyv(dt,c("start","end"))
#Setup output table
stateData = data.table(id = dt$id)
#Remove "-" from days before index, they could get confusing, and initialise
#columns with zero
dayStrings = paste("d",gsub("-", "m", period),sep="")
stateData[,(dayStrings) := 0L]
#Find whether there is an overlap between a specified day in period and a
#subject's events
getStateOnDay = function(dayInd) {
#Get day
day = period[dayInd]
#Create a table with the same number of rows as input dt, with a one day long
#event on the input day
overlapDays = unlist(foverlaps(data.table(start = day,end = day),
dt,
which=TRUE,
nomatch = 0L)$yid)
#Set those days to 1 in the state table
set(stateData,overlapDays,dayInd+1L,1L)
}
#Get states for each row
lapply(dayInds,getStateOnDay)
#Create table for data with one row for each unique ID
reducedStateData = data.table(id = unique(stateData$id))
reducedStateData[,(dayStrings) := 0L]
#Sum a vector of logicals using OR
orSum = function(inputVec) {
return(Reduce("|", c(inputVec)))
}
#Function for finding for each ID if they were in the state on a given day
reduceStatesByID = function(dayInd) {
set(reducedStateData,
NULL,
dayInd+1L,
stateData[,c(1,dayInd+1),with=FALSE][,as.integer(lapply(.SD, orSum)), by=id][,V1])
return(NA)
}
#Apply reduction and sort
lapply(dayInds,reduceStatesByID)
setkey(reducedStateData,id)
【问题讨论】:
-
所以在这里切入正题,
dt和reducedStateData是您想要的最终结果吗? -
@thelatemail 是的,抱歉应该说清楚
标签: r data.table time-series reduce