Numpy vectorize as a decorator with arguments

10,163

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).

Share:
10,163

Related videos on Youtube

green diod
Author by

green diod

Upside down

Updated on June 04, 2022

Comments

  • green diod
    green diod about 2 years

    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?

    • green diod
      green diod over 11 years
      @seberg, your comment about me not doing enough great research was offensive even if you deleted it. If I ask questions here on SO, it's after trying things, reading the docs, going through the manuals and so on. I wouldn't even distrurb you with my dumb questions anyway if I was able to do the kind of great research you're referring to. In your first comment that you also deleted, you talked about the difference about np.float and np.float_ but I didn't see how it could relate to my problem. Now you also downvoted me, I don't care.
  • green diod
    green diod over 11 years
    My numpy version is 1.6.1 .. and I don't get the same behavior as you report but the one I mentioned in my post. In my cas, the first input x is an array of np.float's so why do I get an array of np.int at the end?? But worse, as I mentioned in my OP, I got errors even if I didn't use np.vectorize as a decorator!!
  • seberg
    seberg over 11 years
    it is no the first "input" that matters, but the first "output" and 0 is not a float.
  • green diod
    green diod over 11 years
    @nneonneo I'm afraid that the behavior I got was because of the internal state of my IPython session. But then, I can't figure out why that session got corrupted to the point where the np.vectorize didn't behave like announced in the docs.
  • green diod
    green diod over 11 years
    @seberg the doc says that the output depends on the type of the first input ...