我有一个独特的问题。我已经尝试了一些不同的东西,我会在问题本身后详细说明。
问题: 对于每个用户ID,我需要迭代事件日期并检查每个日期是否在下一个日期的30天内。我有260,000条记录,并且只有一个条目的ID不可忽略不计。数据如下:
id | date1 | date2
1 | 2016-01-01 | 2016-02-12
等等
我尝试过:
简要介绍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的方式)更快的方式,而且速度快而且不是内存密集型?
答案 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