Outer / tensor product in R

Given p vectors x1,x2,...,xp each of dimension d , the best way to calculate their tensor / outer / crusher product ( p -array X with entries X[i1,i2,..ip] = x1[i1]x2[i2]...xp[ip]) ? The cycle is trivial, but stupid. Using outer repeat calls works fine, but doesn't seem like the optimal solution (and will become slower with increasing p, obviously). Is there a better way?

Edit:

I'm the best now

 array(apply(expand.grid(x1, x2, x3), 1, prod), dim=rep(d, 3)) 

who at least "feels better" ...

Edit 2: In response to @Dwin, here is a complete example

 d=3 x1 = 1:d x2 = 1:d+3 x3 = 1:d+6 array(apply(expand.grid(x1, x2, x3), 1, prod), dim=rep(d, 3)) , , 1 [,1] [,2] [,3] [1,] 28 35 42 [2,] 56 70 84 [3,] 84 105 126 , , 2 [,1] [,2] [,3] [1,] 32 40 48 [2,] 64 80 96 [3,] 96 120 144 , , 3 [,1] [,2] [,3] [1,] 36 45 54 [2,] 72 90 108 [3,] 108 135 162 
+6
source share
3 answers

It's hard to beat outer performance. The result is matrix multiplication, which is performed by the BLAS library. Recalling outer does not matter, since the last call will dominate both in speed and in memory. For example, for vectors of length 100, the last call is at least 100 times slower than the previous ...

It is best to get the best performance here to get the best BLAS library for R. By default this is not very good. On Linux, you can pretty easily configure R to use ATLAS BLAS. On Windows, this is more complicated, but possible. See R for Windows FAQs .

 # multiple outer mouter <- function(x1, ...) { r <- x1 for(vi in list(...)) r <- outer(r, vi) r } # Your example d=3 x1 = 1:d x2 = 1:d+3 x3 = 1:d+6 mouter(x1,x2,x3) # Performance test x <- runif(1e2) system.time(mouter(x,x,x)) # 0 secs (less than 10 ms) system.time(mouter(x,x,x,x)) # 0.5 secs / 0.35 secs (better BLAS) 

I replaced my Windows Rblas.dll version of DOTNAME for GOTO BLAS with this place , which improved the time from 0.5 to 0.35 seconds higher.

+5
source

You can use tensor package.

And also %o% function

 A <- matrix(1:6, 2, 3) D <- A %o% A 
+1
source

I am wondering if the kronecker product is what you want. I can’t say from your description of the problem what you need, but the elements from this on a small set of arguments are the same (although in a different order, as in the release of the Chalasani solution, which you criticized as slow:

 kronecker( outer(LETTERS[1:2], c(3, 4, 5),FUN=paste), letters[6:8] ,FUN=paste) [,1] [,2] [,3] [1,] "A 3 f" "A 4 f" "A 5 f" [2,] "A 3 g" "A 4 g" "A 5 g" [3,] "A 3 h" "A 4 h" "A 5 h" [4,] "B 3 f" "B 4 f" "B 5 f" [5,] "B 3 g" "B 4 g" "B 5 g" [6,] "B 3 h" "B 4 h" "B 5 h" 

If you want products, replace either prod or "*". In any case, proposing a set of sets of vectors and the desired result is the best practice when asking questions.

+1
source

Source: https://habr.com/ru/post/905361/


All Articles