0

There is a simple function, which intends to accept a scalar parameter, but also works for a numpy matrix. Why does the function fun works for a matrix?

>>> import numpy as np
>>> def fun(a):
      return 1.0 / a

>>> b = 2
>>> c = np.mat([1,2,3])
>>> c
matrix([[1, 2, 3]])

>>> fun(b)
0.5
>>> fun(c)
matrix([[ 1.        ,  0.5       ,  0.33333333]])

>>> v_fun = np.vectorize(fun)
>>> v_fun(b)
array(0.5)
>>> v_fun(c)
matrix([[ 1.        ,  0.5       ,  0.33333333]])

It seems like fun is vectorized somehow, because the explictly vectorized function v_fun behaves same on matrix c. But their get different outputs on scalar b. Could anybody explain it? Thanks.

Cole
  • 1

2 Answers2

0

What happens in the case of fun is called broadcasting.

General Broadcasting Rules

When operating on two arrays, NumPy compares their shapes element-wise. It starts with the trailing dimensions, and works its way forward. Two dimensions are compatible when

  1. they are equal, or
  2. one of them is 1

If these conditions are not met, a ValueError: frames are not aligned exception is thrown, indicating that the arrays have incompatible shapes. The size of the resulting array is the maximum size along each dimension of the input arrays.

matusko
  • 3,487
  • 3
  • 20
  • 31
  • Thanks.Helped me a lot. – Cole Apr 17 '17 at 08:46
  • *"The size of the resulting array is the maximum size along each dimension of the input arrays."* That's actually slightly inaccurate: `np.zeros((1,0)) + np.zeros((3,1))` gives `array([], shape=(3, 0), dtype=float64)`. – Paul Panzer Apr 17 '17 at 13:29
  • `np.vectorize` does apply broadcasting when working with 2 or more input arguments. But this function only takes one. – hpaulj Apr 17 '17 at 16:49
0

fun already works for both scalars and arrays - because elementwise division is defined for both (their own methods). fun(b) does not involve numpy at all, that just a Python operation.

np.vectorize is meant to take a function that only works with scalars, and feed it elements from an array. In your example it first converts b into an array, np.array(b). For both c and this modified b, the result is an array of matching size. c is a 2d np.matrix, and result is the same. Notice that fun(b) is type array, not matrix.

This not a good example of using np.vectorize, nor an example of broadcasting. np.vectorize is a rather 'simple minded' function and doesn't handle scalars in a special way.

1/c or even b/c works because c, an array 'knows' about division. Similarly array multiplication and addition are defined: 1+c or 2*c.

I'm tempted to mark this as a duplicate of

Python function that handles scalar or arrays

Community
  • 1
  • 1
hpaulj
  • 221,503
  • 14
  • 230
  • 353