【发布时间】:2026-01-14 16:15:02
【问题描述】:
我正在处理包含 230 万条记录的 R 中的大型数据框,其中包含具有开始和停止时间的位置的用户交易。我的目标是创建一个新的数据框,其中包含每个用户/每个位置的连接时间。让我们称之为每小时连接。
交易可能会从 8 分钟到 48 小时不等,因此目标数据框将是大约 1 亿条记录,并且每个月都会增长。
下面的代码显示了最终数据帧的开发方式,尽管总代码要复杂得多。在 Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz、16 核 128GB RAM 上运行总代码大约需要 9 个小时。
library(dplyr)
numsessions<-1000000
startdate <-as.POSIXlt(runif(numsessions,1,365*60*60)*24,origin="2015-1-1")
df.Sessions<-data.frame(userID = round(runif(numsessions,1,500)),
postalcode = round(runif(numsessions,1,100)),
daynr = format(startdate,"%w"),
start =startdate ,
end= startdate + runif(1,1,60*60*10)
)
dfhourly.connected <-df.Sessions %>% rowwise %>% do(data.frame(userID=.$userID,
hourlydate=as.Date(seq(.$start,.$end,by=60*60)),
hournr=format(seq(.$start,.$end,by=60*60),"%H")
)
)
我们希望在(部分)16 个内核上并行化此过程,以加快该过程。第一次尝试是使用multidplyr 包。分区基于daynr
df.hourlyconnected<-df.Sessions %>%
partition(daynr,cluster=init_cluster(6)) %>%
rowwise %>% do(data.frame(userID=.$userID,
hourlydate=as.Date(seq(.$start,.$end,by=60*60)),
hournr=format(seq(.$start,.$end,by=60*60),"%H")
)
) %>% collect()
现在,rowwise 函数似乎需要数据帧作为输入而不是分区。
我的问题是
是否有针对每个核心的分区执行逐行计算的解决方法?
有没有人建议使用不同的 R 包和方法执行此计算?
【问题讨论】:
-
the CRAN Task View about HPC 可能会给你一些想法
-
除了该页面,您可能还想查看
data.table包(对于速度和内存效率,特别是对于大型数据集,这个imo 比dplyr更好)或ff包(可以在磁盘上而不是在 RAM 中处理数据集) -
试试下面的简单改进代码。我会花我的钱,它会比你的多线程执行得更好:
library(data.table) ; res <- setDT(df.Sessions)[, seq.POSIXt(start, end, by = 3600), by = userID] ; res[, `:=`(hourlydate = as.IDate(V1), hournr = hour(V1), V1 = NULL)] -
那么第一行应该是
res <- setDT(df.Sessions)[, seq.POSIXt(start, end, by = 3600), by = .(userID, start, end)] -
尝试了您的代码,并且 hol* f* 它运行得很快!我真的需要更深入地研究你是如何想出这个简单的代码的,但现在一切都为你效劳。
标签: r performance parallel-processing dplyr