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?
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.
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.
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 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.
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__
:
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With