大数据集上的R-diff函数

大数据集上的R-diff函数,r,dataframe,multicore,subset,R,Dataframe,Multicore,Subset,我想在一个真正大的数据框架上使用diff函数:1.4亿行和两列 目标是为每个用户id计算两个连续日期活动之间的间隔。 对于每个用户,第一个活动没有上一个,因此我需要一个NA值 我使用了这个函数,它适用于小数据集,但对于大数据集,它的速度非常慢。我从昨天就开始等了,它还在运行 df2 <- as.vector(unlist(tapply(df$DATE,df$user_id, FUN=function(x){ return (c(NA,diff(x)))}))) df2这里是一个示例,使用

我想在一个真正大的数据框架上使用diff函数:1.4亿行和两列

目标是为每个用户id计算两个连续日期活动之间的间隔。 对于每个用户,第一个活动没有上一个,因此我需要一个NA值

我使用了这个函数,它适用于小数据集,但对于大数据集,它的速度非常慢。我从昨天就开始等了,它还在运行

df2 <- as.vector(unlist(tapply(df$DATE,df$user_id, FUN=function(x){ return (c(NA,diff(x)))})))

df2这里是一个示例,使用数据集上的一些示例数据,该数据集最初有1000万行,有100个用户,
diff
每个数据集有100000个时间点,然后是1.4亿行,有1400个用户,所以时间点的数量相同。这会将时间点转换为列。我可以想象,如果你把用户转移到专栏,速度会更快。我用它作为模板。基本上,它表明,在一个非常大的表上,您可以在<90秒的时间内在单核(i7 2.6 GhZ)上完成(这是使用可能未完全优化的代码):

require(data.table)
##较小的样本数据集-1000万行,100个用户,每个时间点100000个

DT这里是一个示例,使用数据集上的一些示例数据,该数据集最初有1000万行,有100个用户,
diff
10万个时间点,然后是1.4亿行,有1400个用户,因此时间点的数量相同。这会将时间点转换为列。我可以想象,如果你把用户转移到专栏,速度会更快。我用它作为模板。基本上,它表明,在一个非常大的表上,您可以在<90秒的时间内在单核(i7 2.6 GhZ)上完成(这是使用可能未完全优化的代码):

require(data.table)
##较小的样本数据集-1000万行,100个用户,每个时间点100000个

DT如果同时避免使用
tapply
,这会快得多,这相当容易,因为
tapply
调用假定数据已经按
user\u id
DATE
排序

set.seed(21)
N <- 1e6
Data <- data.frame(DATE=Sys.Date()-sample(365,N,TRUE),
                   USER=sample(1e3,N,TRUE))
Data <- Data[order(Data$USER,Data$DATE),]
system.time({
  Data$DIFF <- unlist(tapply(Data$DATE,Data$USER, function(x) c(NA,diff(x))))
})
#   user  system elapsed 
#   1.58    0.00    1.59
Data2 <- Data
system.time({
  Data2$DIFF <- c(NA,diff(Data2$DATE))
  is.na(Data2$DIFF) <- which(c(NA,diff(Data2$USER))==1)
})
#   user  system elapsed 
#   0.12    0.00    0.12
identical(Data,Data2)
# [1] TRUE
set.seed(21)

N如果同时避免
tapply
,这会快得多,这相当容易,因为
tapply
调用假定数据已经按
user\u id
DATE
排序

set.seed(21)
N <- 1e6
Data <- data.frame(DATE=Sys.Date()-sample(365,N,TRUE),
                   USER=sample(1e3,N,TRUE))
Data <- Data[order(Data$USER,Data$DATE),]
system.time({
  Data$DIFF <- unlist(tapply(Data$DATE,Data$USER, function(x) c(NA,diff(x))))
})
#   user  system elapsed 
#   1.58    0.00    1.59
Data2 <- Data
system.time({
  Data2$DIFF <- c(NA,diff(Data2$DATE))
  is.na(Data2$DIFF) <- which(c(NA,diff(Data2$USER))==1)
})
#   user  system elapsed 
#   0.12    0.00    0.12
identical(Data,Data2)
# [1] TRUE
set.seed(21)

N我将研究使用
data.table
来解决涉及如此规模的数据集的问题。您将看到将df转换为data.table的速度大幅提高(
DT将处理小数据集所需的时间乘以小数据集与大数据集的比率。是否花费了那么多时间?回答您的另一个问题,通常情况下,矩阵对象的处理速度比数据帧对象快。@CarlWitthoft矩阵的处理速度要快得多,但R仍将制作数据的后台副本,对吗?这将在一个如此大的数据集上,这可能会减慢它的速度。你能确认你能做到(在一个相同大小的简单向量上)吗仅4秒?因为这不是我的情况。@SimonO101足够正确。我的计算至少提供了一个处理时间的下限。我会研究使用
data.table
来解决涉及如此规模的数据集的问题。您将看到将df转换为data.table的速度有了很大的提高(
DT将处理小数据集所需的时间乘以小数据集与大数据集的比率。是否花费了那么多时间?回答您的另一个问题,通常情况下,矩阵对象的处理速度比数据帧对象快。@CarlWitthoft矩阵的处理速度要快得多,但R仍将制作数据的后台副本,对吗?这将在如此大的数据集上,这可能会减慢速度。你能确认你只能在4秒内完成(在相同大小的简单向量上)吗?因为这不是我的情况。@SimonO101足够正确。我的计算至少提供了处理时间的下限。