Array elementwise operations Array elementwise operations numpy numpy

Array elementwise operations


One "easier way" is to create a NumPy-aware function using numpy.vectorize. A "ufunc" is NumPy terminology for an elementwise function (see documentation here). Using numpy.vectorize lets you use your element-by-element function to create your own ufunc, which works the same way as other NumPy ufuncs (like standard addition, etc.): the ufunc will accept arrays and it will apply your function to each pair of elements, it will do array shape broadcasting just like standard NumPy functions, etc. The documentation page has some usage examples that might be helpful.

In [1]: import numpy as np   ...: def myfunc(a, b):   ...:     "Return 1 if a>b, otherwise return 0"   ...:     if a > b:   ...:         return 1   ...:     else:   ...:         return 0   ...: vfunc = np.vectorize(myfunc)   ...: In [2]: vfunc([1, 2, 3, 4], [4, 3, 2, 1])   ...: Out[2]: array([0, 0, 1, 1])In [3]: vfunc([1, 2, 3, 4], 2)   ...: Out[3]: array([0, 0, 1, 1])


(I'm guessing your talking about simple python list, not numpy.array)

Recursion always making our life easier:

def operate_on_Narray(A, B, function):    try:        return [operate_on_Narray(a, b, function) for a, b in zip(A, B)]    except TypeError as e:        # Not iterable        return function(A, B)

Usage:

>>> x = [[2, 2, 2],...      [2, 2, 2],...      [2, 2, 2]]>>> >>> y = [[3, 3, 3],...      [3, 3, 3],...      [3, 3, 1]]>>> operate_on_Narray(x, y, lambda a, b: a+b)[[5, 5, 5], [5, 5, 5], [5, 5, 3]]

It will work in any other kind of dimensional array:

>>> operate_on_Narray([1, 2, 3], [4, 5, 6], lambda a, b: a*b)[4, 10, 18]


The following transcript from a python 2.7.3 interpreter session illustrates use of builtin function map to apply an elementwise operation to 2D-matrix elements. (Note: operator.add is equivalent to the elementwise_function specified in question, and also equivalent to the lambda expression in the second use of applier.)

>>> import operator>>> def applier(a, b, op):...     return map(lambda ro: map(op, ro[0], ro[1]), zip(a,b))... >>> applier(x, y, operator.add)[[5, 5, 2], [5, 4, 5], [6, 5, 5]]>>> x; y[[2, 2, 1], [2, 2, 2], [3, 2, 2]][[3, 3, 1], [3, 2, 3], [3, 3, 3]]>>> applier(x, y, lambda p,q: p+q)[[5, 5, 2], [5, 4, 5], [6, 5, 5]]>>> applier(x, y, lambda p,q: p-q)[[-1, -1, 0], [-1, 0, -1], [0, -1, -1]]>>> applier(x, y, lambda p,q: p*q)[[6, 6, 1], [6, 4, 6], [9, 6, 6]]

Note, the above has x, y as follows:

x=[[2, 2, 1], [2, 2, 2], [3, 2, 2]]y=[[3, 3, 1], [3, 2, 3], [3, 3, 3]]

As mentioned before, the transcript above is from a python 2.7.3 interpreter session. If this code is run in python 3, it will instead return map objects. One can use a function like the following to see the numbers:

def itemize(m):    return [itemize(e) for e in m] if hasattr(m, '__iter__') else m

With that function in place, the statement

itemize(applier(x, y, operator.add))

returns

[[5, 5, 2], [5, 4, 5], [6, 5, 5]]