-1

I want to get an array containing the element wise multiplication of n>2 arrays. Specifically, is there a way to vectorize the below example code (here n=3 but I will in general need to do this for n>=3) in numpy?

p1=np.array([0.5,0.2,0.3])

p2=np.array([0.3,0.1,0.6])

p3=np.array([0.8,0.1,0.1])

p=np.zeros((p1.shape[0],p2.shape[0],p3.shape[0] ))
for i in range(p1.shape[0]):
    for j in range(p2.shape[0]):
        for k in range(p3.shape[0]):
           p[i,j,k] = p1[i]*p2[j]*p3[k]
PJORR
  • 71
  • 5

2 Answers2

0

You are looking for an outer product. First perform an outer product of p1 and p2, followed by the outer product with p3. The reshaping can be done as desired

prod = np.outer(np.outer(p1, p2), p3)

prod = prod.reshape((p1.shape[0],p2.shape[0],p3.shape[0] ))

EDIT: Generalised solution suggested by @Yann Vernier in the comments below

from functools import reduce
ps = [p1, p2, p3]
prod = reduce(np.outer, ps).reshape([p.shape[0] for p in ps])

# array([[[0.12 , 0.015, 0.015],
#         [0.04 , 0.005, 0.005],
#         [0.24 , 0.03 , 0.03 ]],

#        [[0.048, 0.006, 0.006],
#         [0.016, 0.002, 0.002],
#         [0.096, 0.012, 0.012]],

#        [[0.072, 0.009, 0.009],
#         [0.024, 0.003, 0.003],
#         [0.144, 0.018, 0.018]]])
Sheldore
  • 37,862
  • 7
  • 57
  • 71
  • He said he wants a general method to do it with `n` vectors, not just 3, – dome May 15 '19 at 16:26
  • @dome: Oh, sorry I overlooked. Give me some time to make it more general – Sheldore May 15 '19 at 16:27
  • So generalize it? `prod = reduce(np.outer, ps).reshape([p.shape[0] for p in ps])` – Yann Vernier May 15 '19 at 16:28
  • @YannVernier: Thanks for the pointer. I acknowledged you and your comment in the answer. I hope you don't mind. If you do, feel free to comment and I will delete my answer – Sheldore May 15 '19 at 16:31
  • Thank you for pointing out that this is called outer product. I had no idea! I think my question in the title is more generic than the one my question is marked duplicate for. That question has "outer product" in the title. I'm sure that most people trying to solve a problem like mine would not have known that it is called outer product. Once you know, it is much easier to vectorize. Thanks! – PJORR May 15 '19 at 16:49
0

Here's a generic one for a generic number of input arrays using np.ix_ to make them outer-broadcastable against each other -

In [83]: A = [p1,p2,p3] # list of all input arrays

In [84]: np.multiply.reduce(np.ix_(*A))
Out[84]: 
array([[[0.12 , 0.015, 0.015],
        [0.04 , 0.005, 0.005],
        [0.24 , 0.03 , 0.03 ]],

       [[0.048, 0.006, 0.006],
        [0.016, 0.002, 0.002],
        [0.096, 0.012, 0.012]],

       [[0.072, 0.009, 0.009],
        [0.024, 0.003, 0.003],
        [0.144, 0.018, 0.018]]])
Divakar
  • 218,885
  • 19
  • 262
  • 358