tags:

views:

41

answers:

2

Is it possible to do array broadcasting in numpy with parameters that are vectors?

For example, I know that I can do this

def bernoulli_fraction_to_logodds(fraction):
    if fraction == 1.0:
        return inf
    return log(fraction / (1 - fraction))
bernoulli_fraction_to_logodds = numpy.frompyfunc(bernoulli_fraction_to_logodds, 1, 1)

and have it work with the whole array. What if I have a function that take a 2-element vector and returns a 2-element vector. Can I pass it an array of 2-element vectors? E.g.,

def beta_ml_fraction(beta):
    a = beta[0]
    b = beta[1]
    return a / (a + b)
beta_ml_fraction = numpy.frompyfunc(beta_ml_fraction, 1, 1)

Unfortunately, this doesn't work. Is there a similar function to from_py_func that works. I can hack around this when they are 2-element vectors, but what about when they are n-element vectors?

Thus, input of (2,3) should give 0.4, but input of [[2,3], [3,3]] should give [0.4, 0.5].

+3  A: 

I don't think frompyfunc can do this, though I could be wrong.

Regarding np.vectorize A. M. Archibald wrote:

In fact, anything that goes through python code for the "combine two scalars" will be slow. The slowness of looping in python is not because python's looping constructs are slow, it's because executing python code is slow. So vectorize is kind of a cheat - it doesn't actually run fast, but it is convenient.

So np.frompyfunc (and np.vectorize) are just syntactic sugar -- they don't make Python functions run any faster. After realizing that, my interest in frompyfunc flagged (to near zero).

There is nothing unreadable about a Python loop, so either use one explicitly, or rewrite the function to truly leverage numpy (by writing truly vectorized equations).

import numpy as np

def beta_ml_fraction(beta):    
    a = beta[:,0]
    b = beta[:,1]
    return a / (a + b)


arr=np.array([(2,3)],dtype=np.float)
print(beta_ml_fraction(arr))
# [ 0.4]

arr=np.array([(2,3),(3,3)],dtype=np.float)
print(beta_ml_fraction(arr))
# [ 0.4  0.5]
unutbu
Thanks for the information about vectorization.
Neil G
+1  A: 

When dealing with bidimensional vector array I like to keep the x and y components as the first index. For this I make heavy use of the transpose()

def beta_ml_fraction(beta):
        a = beta[0]
        b = beta[1]
   return a / (a + b)

arr=np.array([(2,3),(3,3)],dtype=np.float) 
print(beta_ml_fraction(arr.transpose()))
# [ 0.4  0.5]

the advantage of this approach is that handling multidimensional array of bi-dimensional vector becomes easiear.

x = np.arange(18,dtype=np.float).reshape(2,3,3)
print(x)
#array([[[  0.,   1.,   2.],
#        [  3.,   4.,   5.],
#        [  6.,   7.,   8.]],
#
#       [[  9.,  10.,  11.],
#        [ 12.,  13.,  14.],
#        [ 15.,  16.,  17.]]])
print(beta_ml_fraction(x))
#array([[ 0.        ,  0.09090909,  0.15384615],
#       [ 0.2       ,  0.23529412,  0.26315789],
#       [ 0.28571429,  0.30434783,  0.32      ]])
Bernardo Kyotoku
Thanks, this solves my problem.
Neil G