0

What is the most efficient way of initializing a NumPy matrix with the results of a function taking the coordinates as arguments?

Currently, I only know how to do it with a double loop, but I heard it's usually not optimal for NumPy matrices.

M = np.zeros((1000,1000))

for i in range(1000):
    for j in range(1000):
        M[i][j] = f(i,j) #where f is the desired function

Is there a better way to implement NumPy matrix with the results of an arbitrary function of coordinates?

I assume that the function does, in fact, depend on two arguments, ie. there are no functions g and h, for which f(x,y) = h(x)g(y). (original: f(x,y) = h(g(x,y))).

8
  • 1
    It depends if your function allows vectorization. Provide more details on how your function looks like Commented Jan 26, 2019 at 18:29
  • Can you function only work with scalar values of i and j? So it has to be called one for each combination of values? There are minor tweaks that might give a 2x speedup, but not much better. Commented Jan 26, 2019 at 18:31
  • Entirely dependent on f, so you'll have to post what f is to get any help.. Commented Jan 26, 2019 at 18:48
  • Unless you post some information about the function, you are unlikely to get anything useful Commented Jan 26, 2019 at 18:49
  • You can perform vectorization if your function allows so. If you need unique values that are independent for each (i,j), then it may not be made faster. Have you looked up the numpy docs ? I would suggest you to have a look at np.apply_along_axis() and edit the question to add some more information about f(). Commented Jan 26, 2019 at 19:08

1 Answer 1

2

There's a serious mismatch between the question and accepted answer. fun is not an arbitrary function of the coordinates. It is a fully 'vectorized' one, one that accepts broadcastable arrays.

In [195]: def fun(i,j): return i*j-j**2
In [196]: 
In [196]: np.fromfunction(fun, (4,4))
Out[196]: 
array([[ 0., -1., -4., -9.],
       [ 0.,  0., -2., -6.],
       [ 0.,  1.,  0., -3.],
       [ 0.,  2.,  2.,  0.]])
In [197]: fun(np.arange(4)[:,None], np.arange(4))
Out[197]: 
array([[ 0, -1, -4, -9],
       [ 0,  0, -2, -6],
       [ 0,  1,  0, -3],
       [ 0,  2,  2,  0]])

All fromfunction does is generate a full set of coordinates, and pass the resulting array(s) to your function:

In [199]: np.indices((4,4))
Out[199]: 
array([[[0, 0, 0, 0],
        [1, 1, 1, 1],
        [2, 2, 2, 2],
        [3, 3, 3, 3]],

       [[0, 1, 2, 3],
        [0, 1, 2, 3],
        [0, 1, 2, 3],
        [0, 1, 2, 3]]])

np.meshgrid and np.mgrid could also be used to generate these coordinates. A function that works with 2d arrays like this is not arbitrary. It is, though, a highly desirable trait when working with numpy.

Your question, or maybe it's the lack of response to our questions, implies that i and j have to be scalar, and hence requiring that each i,j pair gets passed individually to the function. For example j might be used in math.sin(j), or the function has some if test on the i or j value. In that case the fromfunction approach will fail.

Sign up to request clarification or add additional context in comments.

1 Comment

Hey, no "accepted answer" for now :-( —፨— Seriously, thanks for heads up, I have edited my answer...

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.