3

I am worrying that this might be a really stupid question. However I can't find a solution. I want to do the following operation in python without using a loop, because I am dealing with large size arrays. Is there any suggestion?

import numpy as np
a = np.array([1,2,3,..., N]) # arbitrary 1d array
b = np.array([[1,2,3],[4,5,6],[7,8,9]]) # arbitrary 2d array
c = np.zeros((N,3,3))
c[0,:,:] = a[0]*b
c[1,:,:] = a[1]*b
c[2,:,:] = a[2]*b
c[3,:,:] = ...
...
...
c[N-1,:,:] = a[N-1]*b
3
  • By magic..... What you want to do? why a matrix multiply by a vector should be a 3d matrix... what kind of mathematics you would use? Commented Dec 3, 2014 at 11:27
  • you don't get 3d array after muliplying 1d and 2d arrays it'd just give a 2d transformation, if that multiplication is valid Commented Dec 3, 2014 at 11:28
  • It is not an matrix multiplication. But I wanted to avoid using loop and also wanted have a simple array structure. Commented Dec 3, 2014 at 23:57

4 Answers 4

2

My answer uses only numpy primitives, in particular for the array multiplication (what you want to do has a name, it is an outer product).

Due to a restriction in numpy's outer multiplication function we have to reshape the result, but this is very cheap because the data block of the ndarray is not involved.

% python
Python 2.7.8 (default, Oct 18 2014, 12:50:18) 
[GCC 4.9.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> a = np.array((1,2))
>>> b = np.array([[n*m for m in (1,2,3,4,5,6)] for n in (10,100,1000)])
>>> print b
[[  10   20   30   40   50   60]
 [ 100  200  300  400  500  600]
 [1000 2000 3000 4000 5000 6000]]
>>> print np.outer(a,b)
[[   10    20    30    40    50    60   100   200   300   400   500   600
   1000  2000  3000  4000  5000  6000]
 [   20    40    60    80   100   120   200   400   600   800  1000  1200
   2000  4000  6000  8000 10000 12000]]
>>> print "Almost there!"
Almost there!
>>> print np.outer(a,b).reshape(a.shape[0],b.shape[0], b.shape[1])
[[[   10    20    30    40    50    60]
  [  100   200   300   400   500   600]
  [ 1000  2000  3000  4000  5000  6000]]

 [[   20    40    60    80   100   120]
  [  200   400   600   800  1000  1200]
  [ 2000  4000  6000  8000 10000 12000]]]
>>> 
Sign up to request clarification or add additional context in comments.

Comments

1

To avoid Python-level loops, you could use np.newaxis to expand a (or None, which is the same thing):

>>> a = np.arange(1,5)
>>> b = np.arange(1,10).reshape((3,3))
>>> a[:,None,None]*b
array([[[ 1,  2,  3],
        [ 4,  5,  6],
        [ 7,  8,  9]],

       [[ 2,  4,  6],
        [ 8, 10, 12],
        [14, 16, 18]],

       [[ 3,  6,  9],
        [12, 15, 18],
        [21, 24, 27]],

       [[ 4,  8, 12],
        [16, 20, 24],
        [28, 32, 36]]])

Or np.einsum, which is overkill here, but is often handy and makes it very explicit what you want to happen with the coordinates:

>>> c2 = np.einsum('i,jk->ijk', a, b)
>>> np.allclose(c2, a[:,None,None]*b)
True

1 Comment

It seems very simple and easy. Now I also get to understand "a[:,None,None]". Thank you.
0

Didn't understand this multiplication.. but here is a way to make matrix multiplication in python using numpy:

import numpy as np
a = np.matrix([1, 2])
b = np.matrix([[1, 2], [3, 4]])
result = a*b
print(result)

>>>result
matrix([7, 10])

1 Comment

0

What you're doing is an outer product. This operator is available in numpy as multiply.outer:

import numpy as np
a = np.array([1,2,3,4,5])
b = np.array([[1,2,3],
              [4,5,6],
              [7,8,9]])
c = np.multiply.outer(a, b)
print(c)

[[[ 1  2  3]
  [ 4  5  6]
  [ 7  8  9]]

 [[ 2  4  6]
  [ 8 10 12]
  [14 16 18]]

 [[ 3  6  9]
  [12 15 18]
  [21 24 27]]

 [[ 4  8 12]
  [16 20 24]
  [28 32 36]]

 [[ 5 10 15]
  [20 25 30]
  [35 40 45]]]

multiply is a ufunc. According to the documentation of ufunc.outer: "Apply the ufunc op to all pairs (a, b) with a in A and b in B" (here that means applying the multiply operator). Still according to the documentation, doing this is equivalent to:

r = empty(len(A),len(B))
for i in range(len(A)):
    for j in range(len(B)):
        r[i,j] = op(A[i], B[j])  # op = ufunc in question

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.