问题
I've been struggling with the workings of foreach loops in R. To speed up my code I'm trying to change my for loop into a foreach loop with %dopar%.
My goal is to end up with three lists of the same length, each filled with data frames that represent scores between two users (I'm comparing three different calculation methods).
My code used to be (very basic representation):
for (a in 1:5) {
#Just creating some sample data
resultA <- data.frame(matrix(nrow = 40, ncol = 3))
resultB <- data.frame(matrix(nrow = 40, ncol = 3))
resultC <- data.frame(matrix(nrow = 40, ncol = 3))
names(resultA) <- c("User1", "User2", "score")
names(resultB) <- c("User1", "User2", "score")
names(resultC) <- c("User1", "User2", "score")
resultA$User1 <- 1:40
resultB$User1 <- 1:40
resultC$User1 <- 1:40
resultA$User2 <- 40:1
resultB$User2 <- 40:1
resultC$User2 <- 40:1
resultA$score <- sample(40)
resultB$score <- sample(40)
resultC$score <- sample(40)
ListA[[a]] <- resultA
ListB[[a]] <- resultB
ListC[[a]] <- resultC
}
With this code I do indeed get three nice lists with each containing 5 data frames.
Now I'm struggling to translate this to a foreach loop as it can only return one variable (correct me if I'm wrong). So I thought to put the lists in a master list, but then I have trouble getting a list with three sublists as result. Basically I want to append the three lists to themselves, but not to eachother. (So append resultA to ListA, resultB to ListB etc).
I've tried several options for .combine and .init but I can't seem to figure it out. With most functions for .combine I either end up with a huge matrix (which is bad because I can't distinguish the different scoring methods), or lists in lists in lists in lists in ...
EDIT: I solved my problem by using the purrr::transpose() function to transpose the lists in lists. This resulted in one list with three lists (just the way I wanted it). Thanks for the help!
回答1:
Basically, you can convert your code in a nested foreach:
library(doParallel)
registerDoParallel(cl <- makeCluster(2))
res_all <- foreach(a = 1:5) %:% foreach(b = 1:3) %dopar% {
# Just creating some sample data
result <- data.frame(matrix(nrow = 40, ncol = 3))
names(result) <- c("User1", "User2", "score")
result$User1 <- 1:40
result$User2 <- 40:1
result$score <- sample(40)
result
}
stopCluster(cl)
You get a list of 5 lists of 3 data frames:
str(res_all)
If you want to invert the levels, you can e.g. use {purrr}:
str(purrr::transpose(res_all))
来源:https://stackoverflow.com/questions/52894353/return-three-lists-with-foreach-loop-in-r