Applying a function to a 2-D numarray

Steven Bethard steven.bethard at gmail.com
Mon May 16 17:33:22 EDT 2005


Matt Feinstein wrote:
> Well, for example, suppose I want to modify the elements of the matrix
> in some fashion. However, I'm not entirely sure how I want to do it.
> As a strawman, I generate a function with a Boolean test in it that
> multiplies by one factor if the matrix element is in an interval and
> by a different factor if it is outside the interval
> 
> def genfunc(xmin, xmax, f_in, f_out):
>      def booltest(x):
>          in_interval = x > xmin and x < xmax
>          if in_interval:
>               return x*f_in
>         else:
>              return x*f_out
>     return booltest

If efficiency was a concern, I'd probably write this instead as:

py> import numarray as na
py> def genfunc(xmin, xmax, f_in, f_out):
...     def booltest(arr):
...         is_in = na.logical_and(arr > xmin, arr < xmax)
...         is_out = na.logical_not(is_in)
...         return arr*is_in*f_in + arr*is_out*f_out
...     return booltest
...
py> b = genfunc(5, 11, 2, -2)
py> arr = na.arange(20, shape=(4,5))
py> b(arr)
array([[  0,  -2,  -4,  -6,  -8],
        [-10,  12,  14,  16,  18],
        [ 20, -22, -24, -26, -28],
        [-30, -32, -34, -36, -38]])

Sure, it's a little more complex that your version, and you have to 
understand that you're manipulating arrays, not elements of arrays, but 
if you want the efficiency of numarray or Numeric, something like this 
is probably the way to go.

> Generating the function in this way gives me great flexibility in
> deciding exactly what function I apply to the matrix. It's why I want
> to use Python for this analysis. The part of the function  I vary and
> play around with is localized in one place in the 'genfunc' function--
> I can change that and everything else stays the same. However, I
> realize that the gain in flexibility means a loss in efficiency. I'm
> limited to not-so-efficient ways of. For this work, it's OK-- I just
> want to know the best not-so-efficient way of doing the calculation.

If you're not worried about efficiency, your initial suggestion:

     def applyfun(m,f):
         elist = [f(e) for e in m]
         return reshape(elist,m.shape)

seems pretty reasonable.  OTOH, if you're using numarray or Numeric in 
the first place, you're obviously somewhat concerned about efficiency.

STeVe



More information about the Python-list mailing list