1

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.

Márton
  • 35
  • 2

2 Answers2

1

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:

zx8754
  • 52,746
  • 12
  • 114
  • 209
0

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)

Dan Adams
  • 4,971
  • 9
  • 28
  • Yes ofc I get that, just gave an very simplistic example because the original problem would be quite complicated to explain in detail.... But basically I would need to use a loop (or a function) to solve it, but do not need all possible combinations of a nested loop – Márton Apr 13 '22 at 14:05
  • 1
    Then perhaps your example was too simple to represent the critical aspects of your true problem. I just added a few more options, but if this doesn't solve your problem I suggest you make your example sufficiently complex to capture those critical elements. – Dan Adams Apr 13 '22 at 14:13
  • yes you are correct. I basically need an equivalent of Python's zip() for looping through vectors in parallel in R (and not nested) – Márton Apr 13 '22 at 14:17
  • I'm not very familiar with python, but does the `zip()` function actually apply a function to the iterable arguments, or simply concatenate them into a list of tuples? – Dan Adams Apr 13 '22 at 14:21
  • If you just want a list of tuples, you can do `purrr::map2(.x = a, .y = b, `c`)` – Dan Adams Apr 13 '22 at 14:23
  • Thanks seq_along() was perfect for my issue! – Márton Apr 13 '22 at 14:25