如何快速迭代列,检查沿途的事情(R)

时间:2016-06-10 18:17:07

标签: r loops foreach data.table dplyr

我有一个独特的问题。我已经尝试了一些不同的东西,我会在问题本身后详细说明。

问题: 对于每个用户ID,我需要迭代事件日期并检查每个日期是否在下一个日期的30天内。我有260,000条记录,并且只有一个条目的ID不可忽略不计。数据如下:

id |    date1   |   date2
1  | 2016-01-01 | 2016-02-12

等等

我尝试过:

  • foreach(拆分每个ID的事件集,计算,重新组合;遇到内存问题)。
  • data.table,但我不知道我是否用尽了这个选项。
  • 简要介绍dplyr(即:

    mutate(time_btwn=abs(as.numeric(difftime(data$date,lag(data$date2,1),"days")))))
    
  • 我正在运行一个循环遍历所有行的循环for循环。这是非常缓慢的,我希望我不必这样做。代码:

    for ( i in 2:nrow(data) ){
        if ( data$id[ i ] != data$id[ i - 1 ] ){
            next
        } else {
            data$timebtwn[i] <- abs( as.numeric( difftime( data$date1[i], data$date2[ i - 1 ], "days" ) ) )
        }
    }
    

我已经研究过apply和lapply,但是无法完成插入应用或lapply的功能,这将完成我需要的功能(即对于column1中的每个条目,在column2中检查一行并返回如果两行具有相同的id,则日期之间的差异)。

是否有比直接for循环(或使用foreach的方式)更快的方式,而且速度快而且不是内存密集型?

1 个答案:

答案 0 :(得分:1)

由于我没有可以使用的样本数据集,因此我不得不进行一次,因此很难知道您究竟是在做什么,但是:

library(data.table)
library(lubridate)

# generate random date samples
latemail <- function(N, st="2012/01/01", et="2015/12/31") {
  st <- as.POSIXct(as.Date(st))
  et <- as.POSIXct(as.Date(et))
  dt <- as.numeric(difftime(et,st,unit="sec"))
  ev <- sort(runif(N, 0, dt))
  rt <- as_date(st + ev)
}

set.seed(42)
mydat<-data.table(id = as.character(sample.int(1000, 10000, replace =T)),
                  date1 = as_date(latemail(10000)),
                  date2 = as_date(latemail(10000)))
setkey(mydat, id)

mydat[, .(timebtw = abs( as.numeric(difftime(date1, date2), "days" )),
          date1 = date1,
          date2 = date2), by = id]

#     id timebtw      date1      date2
#1:   1       4 2012-01-15 2012-01-11
#2:   1       2 2012-03-21 2012-03-19
#3:   1       9 2012-10-01 2012-10-10
#4:   1       1 2013-08-08 2013-08-09
#5:   1       9 2014-02-11 2014-02-02
#---                                  
#9996: 999       7 2014-10-28 2014-11-04
#9997: 999       9 2015-03-28 2015-04-06
#9998: 999       0 2015-07-22 2015-07-22
#9999: 999      10 2015-09-06 2015-09-16
#10000: 999       8 2015-10-03 2015-10-11

我从this好帖子获得了日期生成功能。如果您正在尝试这样做,请告诉我。此示例具有10,000行和999个唯一ID。为了说明速度:

system.time(
    mydat[, .(timebtw = abs( as.numeric(difftime(date1, date2), "days")),
              date1 = date1,
              date2 = date2), by = id])
#user  system elapsed 
#0.26    0.00    0.26