Numpy vectorize as a decorator with arguments

green diod picture green diod · Feb 20, 2013 · Viewed 8.1k times · Source

I tried to vectorize (agreed, not the most efficient way to do it, but my question is rather on the decorator use) the following function

 @np.vectorize
 def diff_if_bigger(x, y):
     return y - x if y > x else 0

 x = np.array([5.6, 7.0])
 y = 8

 diff_if_bigger(x, y)
 # outputs array([2, 1]) which is not what I want

EDIT: After restarting IPython, the output was OK.

Can anyone explain why the result of diff_if_bigger got tansformed into an array of np.int even if the first argument x is here an aray of np.float, contrarily to what's in the doc????

Now, I want to force a float output, so I did this

 @np.vectorize('np.float')
 def diff_if_bigger(x, y):
     return y - x if y > x else 0
 # Error !!
 # TypeError: Object is not callable.

 @np.vectorize(otypes='np.float')
 def diff_if_bigger(x, y):
     return y - x if y > x else 0
 # Again error !!
 # TypeError: __init__() takes at least 2 arguments (2 given)


 @np.vectorize(otypes=[np.float])
 def diff_if_bigger(x, y):
     return y - x if y > x else 0
 # Still an error !!
 # TypeError: __init__() takes at least 2 arguments (2 given)

By the way, even this

 vec_diff = np.vectorize(diff_if_bigger, otypes=[np.float])

doesn't work!!! So what's going on??

EDIT: In fact, the latter worked after I restarted IPython.

So after my previous two edits, my question is now twofold:

1- How can I use np.vectorize as a decorator with arguments?

2- How can I clean IPython state?

Answer

nneonneo picture nneonneo · Feb 20, 2013

Works for me:

>>> import numpy as np
>>> @np.vectorize
... def diff_if_bigger(x, y):
...      return y - x if y > x else 0
...
>>> diff_if_bigger(np.array([5.6,7.0]), 8)
array([ 2.4,  1. ])

Note that np.vectorize isn't really meant as a decorator except for the simplest cases. If you need to specify an explicit otype, use the usual form new_func = np.vectorize(old_func, otypes=...) or use functools.partial to get a decorator.

Note too that np.vectorize, by default, gets its output type from evaluating the function on the first argument:

The data type of the output of vectorized is determined by calling the function with the first element of the input.

So, you should pass float and return float if you want to ensure that it infers float as the output dtype (e.g. use else 0.0 and pass y = 8.0).