如何优化两个数据框的联接(按日期时间)?

时间:2019-09-13 13:46:01

标签: r

我有一个数据集,其中包含受试者到达和离开的日期和时间。我想知道经过一段时间后的每一分钟有多少个对象。

我首先尝试通过循环来实现此目标,然后根据我在该论坛上看到的内容,使用SQL查询。两种方法都可以,但是非常耗时。


# dataframe with arrival and departure date of the subjetcs
individual <- data.frame(start=c("2018-01-01 13:22", "2018-01-01 14:00","2018-02-07 09:38"),
                         end=c("2018-01-01 15:43", "2018-01-01 14:05","2018-02-23 10:36"))
individual$start <- as.POSIXct(individual$start)
individual$end <- as.POSIXct(individual$end)

# dataframe containing every minute over a lapse time
moment <- data.frame(seq(as.POSIXct("2018-01-01"),as.POSIXct("2018-02-28"), by="1 min"))
colnames(moment) <- "dateTime"


# 1rst method : for every minute in the lapse time, I seek how many rows in "individual" contain this minute
moment[,"nbInd"]=0
for(k in 1:length(moment[,1])){
  print(k)
  moment$nbInd[[k]] <- nrow(individual[(which(moment$dateTime[k]>=individual$start & moment$dateTime[k]<=individual$end)),]  )
}
res <- as.data.frame(table(moment$dateTime)-1)


# 2nd method
dum1 <- sqldf("SELECT * FROM moment  LEFT JOIN individual ON dateTime >= start AND dateTime < end")
res <- as.data.frame(table(dum1$dateTime)-1)

实际上,我的数据框“个人”包含大约900.000行,而我的数据框“矩”也更长。我最终可以将数据帧的“时刻”更改为每10分钟执行一次操作,而不是每1分钟执行一次操作,但这对我来说是一个非常糟糕的解决方案。 我对SQL非常陌生,但是可能会存在更快的SQL查询?还是您看到其他实现此目的的方法?

1 个答案:

答案 0 :(得分:2)

我在SQL方面经验不足,但是由于data.table提供了类似SQL的非等额联接操作,因此这是一个使用非等额联接的data.table解决方案。

library(data.table)
#create data.tables out of the data sets
setDT(moment)
setDT(individual)
#update moment with column N, which is the result of rowcount (.N) of the 
#results of a non-equi join of each row of moment on individual 
#i.e.: N = how many rows in moment are between $start and $end of individual
moment[, N := individual[ moment, 
                          on = .(start <= dateTime, 
                                 end >= dateTime), 
                          .N, 
                          by=.EACHI]$N ]

将起作用...

对于data.table来说,900,000行应该不是一个大问题。