smashbro
smashbro

Reputation: 1224

Using nested for loops to evaluate function at every coordinate - python

I am trying to use a nested for loop to evaluate function f(r) at every combination of 2D polar coordinates.

My current code is:

r = np.linspace(0, 5, 10)
phi = np.linespace(0,2*np.pi, 10)

for i in r:
 for j in phi:
    X = f(r) * np.cos(phi)

print X

When I run this as is it returns X as a 1D array of f(r) and cos(phi) is 1 (ie. phi = 0). However I want f(r) at every value of r, which is then multiplied by its corresponding phi value. This would be a 2D array (10 by 10) where by every combination of r and phi is evaluated.

If you have any suggestions about possible efficiencies I would appreciate it as eventually I will be running this with a resolution much greater than 10 (maybe as high as 10,000) and looping it many thousands of times.

Upvotes: 2

Views: 2087

Answers (3)

Michael
Michael

Reputation: 7736

  1. It's np.linspace not np.linespace.
  2. You're not iterating over the actual data at all, i.e. i and j are not even used in your inner loop. Right now, you're executing the same statement with the same arguments and the same result over and over again. You could have executed the inner statement only one single time, X would be the same.
  3. You need to preallocate a 2D-array for the result.
  4. Iterate over both axes, grab the items of r and phi, do your calculation and put it into the right field of your output array.
  5. Somehow the first point makes me think you never event tried to run your code, as it gives an obvious error message. Anyways, here some solution:

def f(x):
    return x

r = np.linspace(0, 5, 10)
phi = np.linspace(0, 2*np.pi, 10)
X = np.zeros((len(r), len(phi)))

for i in xrange(len(r)):
    for j in xrange(len(phi)):
        X[i,j] = f(r[i]) * np.cos(phi[j])

print X

P.S. Don't go with the solutions, that put the results into ordinary lists, stick with numpy arrays for mathematical problems.

Upvotes: 5

Scott Hunter
Scott Hunter

Reputation: 49803

Instead of assigning to X, you should be adding the most recent 1D array to it. (You'll need to initialize X before the outer loop.)

Edit: You don't need the inner loop; it's computing across all of phi (which is why you get the 1D array) repeatedly. (Note how it doesn't use j). That'll speed things up a bit, AND get you the correct answer!

Upvotes: 0

abarnert
abarnert

Reputation: 365697

When I run this as is it returns X as a 1D array of f(r) and cos(phi) is 1 (ie. phi = 0).

That's because you don't store, print, or do anything else with all those intermediate values you generate. All you do is rebind X to the latest value over and over (forgetting whatever used to be in X), so at the end, it's bound to the last one.

If you want all of those X values, you have to actually store them in some way. For example:

Xs = []
for i in r:
    for j in phi:
        X = f(r) * np.cos(phi)
        Xs.append[X]

Now, you'll have a list of each X instead of just the last one.

Of course in general, the whole reason you use NumPy is to "vectorize" operations instead of looping in the first place. (This allows the loops and the arithmetic to be done in C/C++/Fortran/whatever instead of Python, typically making them an order of magnitude or so faster.) So, if you can rewrite your code to create a 2D array from your 1D array by broadcasting, instead of creating a list of 1D arrays, it will be better…

Upvotes: 1

Related Questions