0

I was always thinking to avoid loop operation in my python code. Numpy really helps, but in some slightly complicated cases, I felt stuck on how to utilize numpy array wisely.

Below is an simple example illustrating my inability, a will be a parameter, and b is an numpy array.

def f(a,b):
    return np.sum( a * b)

so there is no problem if I wish to evaluate this function by a given single parameter and an array.

x = 2
y = np.arange(3)
print (f(x,y))

But sometimes I want to evaluate different parameter value of the function altogether with a fixed array value.

I would try:

x2 = np.array([1,4,5,2,8])
print (f(x2,y))

What I wish to get is surely an array with value:

[f(1,y),f(4,y),f(5,y),f(2,y),f(8,y)]

However, python will try to evaluate the dot product of x and y, since now they are both np arrays and It will report

ValueError: operands could not be broadcast together with shapes (5,) (3,)

How should I overcome this, in numpy array-wise fashion, producing the sequence

[f(1,y),f(4,y),f(5,y),f(2,y),f(8,y)] 

without using loops?

(In this example, I could resolved problem by modify f by:

def f(a,b):
    return a * np.sum(b)

But in most general cases, we cannot factor the parameter out.)

6
  • 2
    in [f(1,y),f(4,y),f(5,y),f(2,y),f(8,y)] y would be an array of length 3. So what numbers would you expect to appear? Should this become a 3x5 array? Commented Nov 12, 2015 at 21:32
  • For the summation calculation, you can just do - x2*y.sum(). Commented Nov 12, 2015 at 21:34
  • To @FabianRost, I am expecting to get 1x5 array, the i'th entry gives the value of f(x2[i],y) Commented Nov 12, 2015 at 21:38
  • @Divakar, I understand this way work, because we can factor the x out of the summation. In general, x and y is not separable before taking summation. For instance if f(a,b) = np.sum (sin( a * b)). Commented Nov 12, 2015 at 21:42
  • @LienongXu In that case do - (np.sin(y[:,None]*x2)).sum(0). As long there is a ufunc for it, its doable that way. Commented Nov 12, 2015 at 21:44

1 Answer 1

2

np.newaxis is a very handy tool for cases like this, and gives you a bit more control over broadcasting. In this case, you'll want to add a new axes to give numpy some hints about where to broadcast:

>>> x = np.array([1,4,5,2,8])
>>> y = np.arange(3)
>>> x[:,np.newaxis] * y
array([[ 0,  1,  2],
       [ 0,  4,  8],
       [ 0,  5, 10],
       [ 0,  2,  4],
       [ 0,  8, 16]])

If you'd like the sums along the second axis, you can sum like this:

>>> (x[:, np.newaxis] * y).sum(axis=1)
array([ 3, 12, 15,  6, 24])
Sign up to request clarification or add additional context in comments.

5 Comments

np.newaxis is redundant in y[np.newaxis,:].
Also, I think OP is summing elements along the second axis for the desired output.
Thanks - didn't see all of the comments on the question.
@pnhgiol, I will take it. Valuable answer.
numpy might not require y[np.newaxis, :], but dumb humans might find it clearer. I could even omit the ':', and use y[None] (but that would not add clarity).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.