Home > Mobile >  Alternative to nested for loop in R without all possible combinations
Alternative to nested for loop in R without all possible combinations

Time:04-14

Imagine I have this bit of nested for loop, which prints all combinations of a and b

a = c(1,2,3,4)
b = c(2,3,4,5)

for(i in a){
  for(k in b){
    print(i   k)
  }}

So the output looks like this

[1] 3
[1] 4
[1] 5
[1] 6
[1] 4
[1] 5
[1] 6
[1] 7
[1] 5
[1] 6
[1] 7
[1] 8
[1] 6
[1] 7
[1] 8
[1] 9

How do I loop through the two loops to get a result with only 4 items, the sum of elements from a and b with the same index, akin to looping through a dictionary in Python? I would like to have result like this:

[1] 3
[1] 5
[1] 7
[1] 9

or this

[1] 3 5 7 9 

Whereby I simply add up a and b like adding up two columns in a dataframe to produce a third of the same length.

I appreciate any help.

CodePudding user response:

As pointed out in the comments, in R, mathematical operators such as are Vectorized. This means that by default you can feed them vectors as arguments and they will know how to walk through the elements in each input vector. Therefore simply doing a b will give the desired result. If you really want to do this as a loop, then you can don't need to nest it - simply take a single index, i, to pull elements from both input vectors. Another option that might be helpful here is purrr::map2() which applies the specified function across two input lists.

However it's worth noting that if you did want to see all pairwise combinations, you could use the outer() function.

# test vectors
a = c(1,2,3,4)
b = c(2,3,4,5)

# operate pairwise through the two vectors
a   b
#> [1] 3 5 7 9

# go through vectors as a loop
for(i in seq_along(a)){
      print(a[i]   b[i])
}
#> [1] 3
#> [1] 5
#> [1] 7
#> [1] 9

# for more complex function can use purrr::map2 to run on two input lists
purrr::map2_dbl(.x = a, .y = b, ` `)
#> [1] 3 5 7 9

# operate on all combinations
outer(a, b, ` `)
#>      [,1] [,2] [,3] [,4]
#> [1,]    3    4    5    6
#> [2,]    4    5    6    7
#> [3,]    5    6    7    8
#> [4,]    6    7    8    9

Created on 2022-04-13 by the reprex package (v2.0.1)

CodePudding user response:

Try mapply:

mapply(` `, a, b)
# [1] 3 5 7 9

We can replace any other function, for example paste or *:

mapply(paste, a, b)
# [1] "1 2" "2 3" "3 4" "4 5"
mapply(`*`, a, b)
# [1]  2  6 12 20

In R, loops are wrapped into *apply functions, see:

  • Related