1

Say you have two (or more) numpy ndarrays of equal size (meaning they have equal number of elements) like:

A = np.array([[1],[2],[3]]) #Define a 3-element column vector
B = np.array([1,2,3]) #Define a 3-element row vector

Given that numpy's documentation advertises the * and / operators as "elementwise" between two ndarray types why do the following:

AtimesB = A*B
AoverB = A/B

return:

array([[1, 2, 3],
       [2, 4, 6],
       [3, 6, 9]]) #AtimesB
array([[1.        , 0.5       , 0.33333333],
       [2.        , 1.        , 0.66666667],
       [3.        , 1.5       , 1.        ]]) #AoverB

instead of:

array([1,4,9])
array([1,1,1])

To my knowledge, it is the @ operator which is meant to do matrix multiplications and np.divide handles the matrix divisions. What am I missing here? Is this the way numpy handles ambiguity regarding array shapes?

J.A. Ferrand
  • 218
  • 1
  • 9
  • 1
    numpy doesn't have the concept of row (column) vector. A 1d array represents both row and column vectors in linear algebra. In your case, your "column vector" is 2d and "row vector" is 1d. `*` and `/` give matrix operations due to [numpy broadcasting](https://numpy.org/doc/stable/user/basics.broadcasting.html). – Psidom Jun 21 '21 at 16:35
  • I think the technical term for this operation is the 'outer product' of the two vectors. It can also be done with [`np.outer`](https://numpy.org/doc/stable/reference/generated/numpy.outer.html). Someone actually explained how broadcasting works yesterday in [this answer](https://stackoverflow.com/a/68059457/1609514). – Bill Jun 21 '21 at 16:46
  • 1
    `shape` gives more information than `size`. There's more to `element-wise` operations than just the number of elements. One array is (3,1) shape, the other (3,). For broadcasting purposes that (3,) is equivalent to (1,3). Together you get a (3,3), an 'outer' operation. – hpaulj Jun 21 '21 at 17:52

2 Answers2

2

A must be a row too to get the result you expect!

>>> A
array([[1],
       [2],
       [3]])
>>> A.T
array([[1, 2, 3]])
>>> A.T * B
array([[1, 4, 9]])
>>> A.T / B
array([[1., 1., 1.]])
ti7
  • 16,375
  • 6
  • 40
  • 68
2

np.divide actually is for element wise division. The element wise operations using * or / are only done if the arrays are of equal shape (and not size). Otherwise the arrays are broadcasted if possible. In order to guarantee element wise multiplication, you can use np.multiply.

fgoudra
  • 751
  • 8
  • 23