Return three lists with foreach loop in R

一曲冷凌霜 提交于 2021-02-10 19:35:42

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!