5

I am trying to vectorize a function which has 2 inputs, and outputs a np.array, of shape =(4,). The function looks like this:

def f(a, b):
    return np.array([a+b, a-b, a, b])

I was able to vectorize the function, using the signature parameter, however it only works if I exclude one of the parameters using the excluded argument of np.vectorize:

This works:

vec = np.vectorize(f, signature='()->(n)', excluded=[1])
x = np.arange(5)
y = 3
vec(x, y)

>> output:
array([[ 3, -3,  0,  3],
       [ 4, -2,  1,  3],
       [ 5, -1,  2,  3],
       [ 6,  0,  3,  3],
       [ 7,  1,  4,  3]])

However if I take out the excluded argument, things don't go as planned.

This does not work:

vec = np.vectorize(f, signature='()->(n)')
x = np.arange(5)
y = 3
vec(x, y)

>> Error:
TypeError: wrong number of positional arguments: expected 1, got 2

How can I make the vectorized function able to receive an array/list of input values for either one (or both) of the input parameters?

The expected output would be a vec function which would enable calling it with multiple inputs for either one of the input parameters.

1 Answer 1

5
In [237]: f1 = np.vectorize(f, signature='(),()->(n)')                          
In [238]: f1(np.arange(5),3)                                                    
Out[238]: 
array([[ 3, -3,  0,  3],
       [ 4, -2,  1,  3],
       [ 5, -1,  2,  3],
       [ 6,  0,  3,  3],
       [ 7,  1,  4,  3]])

In [241]: f1(np.arange(5),np.ones((4,5))).shape                                 
Out[241]: (4, 5, 4)
In [242]: f1(np.arange(5),np.ones((1,5))).shape                                 
Out[242]: (1, 5, 4)

frompyfunc returns a object dtype array:

In [336]: f2 = np.frompyfunc(f,2,1)                                             
In [337]: f2(np.arange(5), 3)                                                   
Out[337]: 
array([array([ 3, -3,  0,  3]), array([ 4, -2,  1,  3]),
       array([ 5, -1,  2,  3]), array([6, 0, 3, 3]), array([7, 1, 4, 3])],
      dtype=object)
In [338]: _.shape                                                               
Out[338]: (5,)

np.vectorize, without the signature, uses frompyfunc, but adds its own dtype conversion.


In [340]: f1(np.arange(5), np.arange(3)) 
ValueError: shape mismatch: objects cannot be broadcast to a single shape

This fails for the same reason the following addition fails:

In [341]: np.arange(5)+np.arange(3)                                             
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-341-fb1c4f4372da> in <module>
----> 1 np.arange(5)+np.arange(3)

ValueError: operands could not be broadcast together with shapes (5,) (3,) 

To get a (5,3) result we need to make the first argument (5,1) shape:

In [342]: np.arange(5)[:,None]+np.arange(3)                                     
Out[342]: 
array([[0, 1, 2],
       [1, 2, 3],
       [2, 3, 4],
       [3, 4, 5],
       [4, 5, 6]])
Sign up to request clarification or add additional context in comments.

6 Comments

Rather monosyllabic by your standards ;-)
@PaulPanzer, I have mixed feels about this signature method. It's an interesting idea, but it runs even slower than the regular vectorize.
@hpaulj, I would expect another behavior... perhaps vectorize is not the function I should be using? For the case of f1(x, y), where x has n elements, and y has m elements, I would expect to be returned an array of dimensions n x m, where each element is f(x_i, y_j) for 0<i<n, 0<j<m. Then each element of this array would itself be a 4-item vector, as output by f(a,b)
@hpaulj not sure why we need to pass a 2-dim array as the second parameter. I would expect to call f1(np.arange(5),np.arange(3)) and get a shape (3, 5, 4)
The (4,5,4) array is a (n, m, 4) array. I just added a frompyfunc example that creates a (n,m) object dtype array, where each element is 4 element array.
|

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.