Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to numpy.vectorize an instance method?

I've found that the numpy.vectorize allows one to convert 'ordinary' functions which expect a single number as input to a function which can also convert a list of inputs into a list in which the function has been mapped to each input. For example, the following tests pass:

import numpy as np
import pytest


@np.vectorize
def f(x):
    if x == 0:
        return 1
    else:
        return 2


def test_1():
    assert list(f([0, 1, 2])) == [1, 2, 2]

def test_2():
    assert f(0) == 1

if __name__ == "__main__":
    pytest.main([__file__])

However, I've not been able to get this to work for an instance method which makes use of an instance attribute. For example:

class Dummy(object):
    def __init__(self, val=1):
        self.val = val

    @np.vectorize
    def f(self, x):
        if x == 0:
            return self.val
        else:
            return 2


def test_3():
    assert list(Dummy().f([0, 1, 2])) == [1, 2, 2]

This test fails:

=================================== FAILURES ===================================
____________________________________ test_3 ____________________________________

    def test_3():
>       assert list(Dummy().f([0, 1, 2])) == [1, 2, 2]

test_numpy_vectorize.py:31: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/numpy/lib/function_base.py:2739: in __call__
    return self._vectorize_call(func=func, args=vargs)
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/numpy/lib/function_base.py:2809: in _vectorize_call
    ufunc, otypes = self._get_ufunc_and_otypes(func=func, args=args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <numpy.lib.function_base.vectorize object at 0x106546470>
func = <function Dummy.f at 0x10653a2f0>, args = [array([0, 1, 2])]

    def _get_ufunc_and_otypes(self, func, args):
        """Return (ufunc, otypes)."""
        # frompyfunc will fail if args is empty
        if not args:
            raise ValueError('args can not be empty')

        if self.otypes is not None:
            otypes = self.otypes
            nout = len(otypes)

            # Note logic here: We only *use* self._ufunc if func is self.pyfunc
            # even though we set self._ufunc regardless.
            if func is self.pyfunc and self._ufunc is not None:
                ufunc = self._ufunc
            else:
                ufunc = self._ufunc = frompyfunc(func, len(args), nout)
        else:
            # Get number of outputs and output types by calling the function on
            # the first entries of args.  We also cache the result to prevent
            # the subsequent call when the ufunc is evaluated.
            # Assumes that ufunc first evaluates the 0th elements in the input
            # arrays (the input values are not checked to ensure this)
            args = [asarray(arg) for arg in args]
            if builtins.any(arg.size == 0 for arg in args):
                raise ValueError('cannot call `vectorize` on size 0 inputs '
                                 'unless `otypes` is set')

            inputs = [arg.flat[0] for arg in args]
>           outputs = func(*inputs)
E           TypeError: f() missing 1 required positional argument: 'x'

Is it possible to apply numpy.vectorize to an instance method?

like image 786
Kurt Peek Avatar asked Feb 26 '18 04:02

Kurt Peek


People also ask

Does NumPy use vectorization?

The concept of vectorized operations on NumPy allows the use of more optimal and pre-compiled functions and mathematical operations on NumPy array objects and data sequences. The Output and Operations will speed up when compared to simple non-vectorized operations. Example 1: Using vectorized sum method on NumPy array.

Does NumPy vectorize fast?

Again, some have observed vectorize to be faster than normal for loops, but even the NumPy documentation states: “The vectorize function is provided primarily for convenience, not for performance.

What does NP vectorize do in python?

vectorize() function. The vectorize() function is used to generalize function class. Define a vectorized function which takes a nested sequence of objects or numpy arrays as inputs and returns an single or tuple of numpy array as output.

What does it mean to vectorize in python?

What is Vectorization ? Vectorization is used to speed up the Python code without using loop. Using such a function can help in minimizing the running time of code efficiently.


1 Answers

Simple solution without modifying the class

You can use np.vectorize directly on the method on the instance:

class Dummy(object):

    def __init__(self, val=1):
        self.val = val

    def f(self, x):
        if x == 0:
            return self.val
        else:
            return 2


vec_f = np.vectorize(Dummy().f) 


def test_3():
    assert list(vec_f([0, 1, 2])) == [1, 2, 2]

test_3()

You can also create a vectorized function vec_f in your __init__:

Adding a vectorized version to the instance

class Dummy(object):

    def __init__(self, val=1):
        self.val = val
        self.vec_f = np.vectorize(self.f) 

    def f(self, x):
        if x == 0:
            return self.val
        else:
            return 2


def test_3():
    assert list(Dummy().vec_f([0, 1, 2])) == [1, 2, 2]

or with a different naming scheme:

class Dummy(object):

    def __init__(self, val=1):
        self.val = val
        self.f = np.vectorize(self.scalar_f) 

    def scalar_f(self, x):
        if x == 0:
            return self.val
        else:
            return 2


def test_3():
    assert list(Dummy().f([0, 1, 2])) == [1, 2, 2]

test_3()

    test_3()
like image 128
Mike Müller Avatar answered Sep 28 '22 04:09

Mike Müller