Home > Software engineering >  Sum each single element in a list with other individual elements in R?
Sum each single element in a list with other individual elements in R?

Time:06-29

Similar questions have been asked before about summing elements of a list. But my problem is a little different than the other questions.

I have a list of vectors. I am trying to sum the 1st element of the 1st vector with each single element from the other vectors in my list. Then I want to sum the 2nd element in my 1st vector with every other individual element from the other vectors in my list... and so on.

Hopefully my example will explain what Im trying to do. For example, if my list looks like this:

l <- list(
  a = c(1,2,3),
  b = c(10,4), 
  c = c(8,5)
)

Writing out explicitly what im trying to do would look like:

1 10 8
1 10 5
1 4 8
1 4 5
2 10 8
2 10 5
2 4 8
2 4 5
3 10 8
3 10 5
3 4 8
3 4 5

In other words, take:

 l[[1]][1]   l[[2]][1]   l[[3]][1]
 l[[1]][1]   l[[2]][1]   l[[3]][2]
 l[[1]][1]   l[[2]][2]   l[[3]][1]
 l[[1]][1]   l[[2]][2]   l[[3]][2]
 l[[1]][2]   l[[2]][1]   l[[3]][1]... and so on for each element

Consequently, my final desired output would look like:

[1] 19 16 13 10 20 17 14 11 21 18 15 12

Any suggestions as to how I could do this?

EDIT: Additionally, to complicate matters more, I need to return the values in the order that I show when I wrote out all the sums explicitly. So the result has to match my desired output.

CodePudding user response:

So you aim to compute a[i] b[j] c[k]. To match your specific order, we can do

## the reason for using rev(l) instead of l is explained below
c(Reduce(function (u, v) outer(u, v, " "), rev(l)))
# [1] 19 16 13 10 20 17 14 11 21 18 15 12

The difference between using l and rev(l) is how fast i, j and k vary.

  • if using l, the speed is i > j > k;
  • if using rev(l), the speed is k > j > i.

The magic (or convenience of outer), is that before we flattening the results using c(), the storage is an interpretable 3D array.

  • if using l, we have arr[i, j, k] = a[i] b[j] c[k];
  • if using rev(l), we have arr[k, j, i] = a[i] b[j] c[k].

The expand.grid solution by thelatemail is also brilliant. expand.grid produces a data frame, so the final rowSums will have to coerce the data frame to a matrix first. But as thelatemail commented, the performance penalty of expand.grid is unlikely to be noticeable unless we have long vectors. (Thanks to thelatemail for reminding me of this function.)

CodePudding user response:

Another option, based on making the combinations of every value across l in three columns, and taking the sum across each row.

rowSums(expand.grid(rev(l)))
#[1] 19 16 13 10 20 17 14 11 21 18 15 12
  •  Tags:  
  • r
  • Related