Numpy: an external product of n vectors

I am trying to do something simple in numpy, and I'm sure there should be an easy way to do this.

Basically, I have a list of n vectors with different lengths. If v1[i] is the ith entry of the first vector, then I want to find an n dimensional array A such that

 A[i,j,k...] = v1[i] v2[j] v3[k] ... 

My problem is that:

  • outer takes only two vector arguments.

  • einsum requires a parameter like "abcd ..." which seems superfluous.

  • kron requires what seems like a pretty complicated restructuring, and takes only two arguments.

I would like to avoid as many difficulties as possible in order to avoid errors. Therefore, I prefer one team.

So far, I have everything I have:

  vs = [v1, v2, v3 ...] shape = map(len, vs) # specify the orientation of each vector newshapes = diag(array(shape)-1)+1 reshaped = [x.reshape(y) for x,y in zip(vs, newshapes)] # direct product A = reduce(lambda a,b: a*b, reshaped, 1) 
+8
python arrays numpy
source share
2 answers

Use the following line code:

 reduce(np.multiply, np.ix_(*vs)) 

np.ix_() will do the external transfer, you need to reduce it, but you can pass ufunc np.multiply without a lambda function.

Here is a comparison:

 import numpy as np vs = [np.r_[1,2,3.0],np.r_[4,5.0],np.r_[6,7,8.0]] shape = map(len, vs) # specify the orientation of each vector newshapes = np.diag(np.array(shape)-1)+1 reshaped = [x.reshape(y) for x,y in zip(vs, newshapes)] # direct product A = reduce(lambda a,b: a*b, reshaped, 1) B = reduce(np.multiply, np.ix_(*vs)) np.all(A==B) 

Repeat:

 True 
+8
source share

There is an alternative line of code:

 reduce(np.multiply.outer, vs) 

For me, this is more transparent than np.ix_(*vs) building and supporting multidimensional arrays such as this question .

The terms are the same within the tolerance:

 import numpy as np from functools import reduce def outer1(*vs): return np.multiply.reduce(np.ix_(*vs)) def outer2(*vs): return reduce(np.multiply.outer, vs) v1 = np.random.randn(100) v2 = np.random.randn(200) v3 = np.random.randn(300) v4 = np.random.randn(50) %timeit outer1(v1, v2, v3, v4) # 1 loop, best of 3: 796 ms per loop %timeit outer2(v1, v2, v3, v4) # 1 loop, best of 3: 795 ms per loop np.all(outer1(v1, v2, v3, v4) == outer2(v1, v2, v3, v4)) # True 
+1
source share

All Articles