Outer loop variable in nested R foreach loop
Asked Answered
A

1

10

I'm trying to use the foreach package in a nested loop, but my inner loop don't recognizes the outer's counter, what m I missing?

v3 <- search.compounds.by.mass(100.05,0.5)
foreach(j=2:length(v2)) %:% {
    foreach(i=1:length(v3), .combine=rbind) %dopar% {
        write.table(paste(v3[i], paste(get.reactions.by.compound(v3[i]), collapse=" "), sep=" "), "file1",quote=FALSE, row.names=FALSE, col.names=FALSE, append=TRUE)
        write.table(paste(v3[i], paste(get.pathways.by.compounds(v3[i]), collapse=" "), sep=" "), "file2",quote=FALSE, row.names=FALSE, col.names=FALSE, append=TRUE)
        v3 <- search.compounds.by.mass(v2[j],0.5)
    }
}
Agnew answered 12/3, 2012 at 20:42 Comment(1)
What is the error message? Also, what is in the variable v2 (you can use dput(v2) so we can reproduce it)Rosary
H
27

The problem is that you are incorrectly applying the %:% operator. It is designed to merge two foreach objects, resulting in a single foreach object that can be used to repeatedly evaluate whatever expression you supply to it. So, if you want to use %:%, you need to first merge the two foreach() statements, and then use the resulting object to drive a single call to %do% (or in your case, %dopar%). See (1) below for an example.

Alternatively, if you want to nest the two foreach() objects, use %do% twice, as in (2) below.

Either way works, although for parallel jobs I might prefer the one using %:%. Your code, though, like (3) below, combines elements of the two strategies to produce a hybrid that can't do anything.

X <- c("A", "B")
Y <- 1:3

## (1) EITHER merge two 'foreach' objects using '%:%' ...
foreach (j = X, .combine = c) %:% foreach(i = Y, .combine = c) %do% {
    paste(j, i, sep = "")
}
# [1] "A1" "A2" "A3" "B1" "B2" "B3"


## (2) ... OR Nest two 'foreach' objects using a pair of '%do%' operators ...
foreach(j = X, .combine = c) %do% {
    foreach(i = Y, .combine = c) %do% {
        paste(j, i, sep = "")
    }
}
# [1] "A1" "A2" "A3" "B1" "B2" "B3"


## (3) ... BUT DON'T use a hybrid of the approaches.
foreach(j = X, .combine = c) %:% {
    foreach(i = Y, .combine = c) %do% {
        paste(j, i, sep = "")
    }
}
# Error in foreach(j = X, .combine = c) %:% { : 
#   "%:%" was passed an illegal right operand
Hecht answered 12/3, 2012 at 21:34 Comment(2)
Good to hear. By the way, if you want to read more about some of the decisions involved in how to structure nested loops, type vignette("nested") at the R command line.Loidaloin
It's painful to note that the vignette shows the right way to do it, and explicitly states it's a binary operator, but it's so easy to make this mistake.Skulduggery

© 2022 - 2024 — McMap. All rights reserved.