[英]putting `mclapply` results back onto data.frame
我有一個非常大的 data.frame
,我想對其應用相當復雜的功能,以計算新列。 我想並行執行。 這類似於在r listserve上發布的問題,但是第一個答案是錯誤的,第二個答案是無用的。
由於parallel
包,我已經弄清了所有東西,除了如何將輸出放回到數據幀上。 這是顯示我所擁有的MWE:
library(parallel)
# Example Data
data <- data.frame(a = rnorm(200), b = rnorm(200),
group = sample(letters, 200, replace = TRUE))
# Break into list
datagroup <- split(data, factor(data$group))
# execute on each element in parallel
options(mc.cores = detectCores())
output <- mclapply(datagroup, function(x) x$a*x$b)
output
結果是數字向量列表。 我需要在可以附加到data
的列中添加它們。 我一直在遵循do.call(cbind, ...)
但是我有兩個名稱相同的列表,而不是我要加入的單個列表。 melt(output)
給我一個向量,但是它的行與data
順序不同。
從評論轉換為答案
這似乎可行:
data <-
do.call(
rbind, mclapply(
split(data, data$group),
function(x){
z <- x$a*x$b
x <- as.data.frame(cbind(x, newcol = z))
return(x)
}))
rownames(data) <- seq_len(nrow(data))
head(data)
# a b group newcol
#1 -0.6482428 1.8136254 a -1.17566963
#2 0.4397603 1.3859759 a 0.60949714
#3 -0.6426944 1.5086339 a -0.96959055
#4 -1.2913493 -2.3984527 a 3.09724030
#5 0.2260140 0.1107935 a 0.02504087
#6 2.1555370 -0.7858066 a -1.69383520
由於您使用的是“非常大”的data.frame(大約有多大?),因此您是否考慮過使用dplyr
或data.table
來做什么? 對於大型數據集,使用其中之一可能會比使用mclapply
。 等效為:
library(dplyr)
data %>%
group_by(group) %>%
mutate(newcol = a * b)
library(data.table)
setDT(data)[, newcol := a*b, by=group]
有點過時,但這可能有所幫助。
如果您有很多分歧,rbind會殺死您的表現。
使用unsplit函數要快得多。
results <- mclapply( split(data, data$group), function(x) x$a*x$b)
resultscombined <- unsplit (results, data$group)
data$newcol <- resultscombined
是的,記憶力大減,因此要取決於您的需求。
我目前無法將parallel
程序包下載到我的計算機上。 在這里,我發布了一個解決方案,該解決方案使用snow
軟件包進行並行計算,可用於我的常規設置。
該解決方案只是在開始時對data.frame進行排序,然后合並輸出列表並調用c()
。 見下文:
library(snow)
library(rlecuyer)
# Example data
data <- data.frame(a = rnorm(200), b = rnorm(200),
group = sample(letters, 200, replace = TRUE))
data <- data[order(data$group),]
# Cluster setup
clNode <- list(host="localhost")
localCl <- makeSOCKcluster(rep(clNode, 2))
clusterSetupRNG(localCl, type="RNGstream", seed=sample(0:9,6,replace=TRUE))
clusterExport(localCl, list=ls())
# Break into list
datagroup <- split(data, factor(data$group))
output <- clusterApply(localCl, datagroup, function(x){ x$a*x$b })
# Put back and check
data$output <- do.call(c, output)
data$check <- data$a*data$b
all(data$output==data$check)
# Stop cluster
stopCluster(localCl)
受到@beginneR和我們對dplyr
熱愛的dplyr
,我做了一些擺弄,並認為實現這一目標的最佳方法是
rbind_all( mclapply(split(data, data$group), fun(x) as.data.frame(x$a*x$b)))
使用多核過程按組計算均值:
library(dplyr)
x <- group_by(iris, Species)
indices <- attr(x,"indices")
labels <- attr(x,"labels")
require(parallel)
result <- mclapply(indices, function(indx){
data <- slice(iris, indx + 1)
## Do something...
mean(data$Petal.Length)
}, mc.cores =2)
out <- cbind(labels,mean=unlist(result))
out
## Species mean
## 1 setosa 1.462
## 2 versicolor 4.260
## 3 virginica 5.552
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.