2

I want to broadcast a function f over a vectors so that the result is a matrix P where P[i,j] = f(v[i], v[j]). I know that I can do it simply:

P = zeros( (v.shape[0], v.shape[0]) )
for i in range(P.shape[0]):
    for j in range(P.shape[0]):
        P[i, j] = f(v[i,:], v[j,:])

or more hacky:

from scipy.spatial.distance import cdist
P = cdist(v, v, metric=f) 

But I am looking for the fastest and neatest way to do it. This seems like a function of broadcasting that numpy should have built-in. Any suggestions?

4
  • If it works, cdist looks like a pretty clean way of doing this. In the case of a callable metric, cdist does exactly what your code is doing. Commented Sep 19, 2014 at 0:42
  • So f(a,b) takes 2 1d arrays, and returns a scalar? Commented Sep 19, 2014 at 1:09
  • f1 = functools.partial(cdist, metric=f) would hide the cdist usage. Commented Sep 19, 2014 at 3:18
  • @Gioelelm I am almost sure you can avoid the loops perhaps redesigning a bit your code... where do you use P[i, j]... do you need all the distance matrix or only to find the closest points for some reason... in that case, check scipy.spatial.distance.cKDTree().. Commented Sep 19, 2014 at 16:22

1 Answer 1

1

I believe what you search for is numpy.vectorize. Use it like so:

def f(x, y):
    return x + y
v = numpy.array([1,2,3])
# vectorize the function
vf = numpy.vectorize(f)
# "transposing" the vector by producing a view with another shape
vt = v.reshape((v.shape[0], 1)
# calculate over all combinations using broadcast
vf(v, vt)

Output:
array([[ 2.,  3.,  4.],
       [ 3.,  4.,  5.],
       [ 4.,  5.,  6.]])
Sign up to request clarification or add additional context in comments.

5 Comments

vectorize doesn't speed it up. It just wraps the loop(s), while giving access to broadcasting machinery.
Maybe I'm wrong but believe thats exactly what he wants. Speedy numpy-level loops while being memory efficient via broadcasting.
But I don't see where broadcasting is used in his sample code.
@itai Yes that is what I wanted, this is for sure faster than my loop
@hpaulj you probably got it yourself but for posterity - v is broadcasted "vertically" (shape (3,1) to (3,3)) and vt is broadcasted "horizontally" (shape (1,3) to (3,3)).

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.