0

I have three ndarrays as follows, where x and y are my coordinate grids and z is my data:

x: [[-11.   -11.   -11.   -11.   -11.  ]
 [ -9.25  -9.25  -9.25  -9.25  -9.25]
 [ -7.5   -7.5   -7.5   -7.5   -7.5 ]
 [ -5.75  -5.75  -5.75  -5.75  -5.75]
 [ -4.    -4.    -4.    -4.    -4.  ]]

y: [[51.   52.25 53.5  54.75 56.  ]
 [51.   52.25 53.5  54.75 56.  ]
 [51.   52.25 53.5  54.75 56.  ]
 [51.   52.25 53.5  54.75 56.  ]
 [51.   52.25 53.5  54.75 56.  ]]

z: [[ 0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.]
 [ 0. 21.  0.  0.  0.]
 [21. 21.  4.  0.  0.]
 [21. 21.  4.  4.  0.]]

I wish to do something like this:

coords = np.stack((x, y)).T
for (x,y), value in np.ndenumerate(z):    
    xx,yy = coords[x][y]
    if not m.is_land(xx,yy):
        z[x][y] = 0 

How do I do this correctly in numpy? Better still would be to create a new array instead of trying to change z.

UPDATE

if I do print(z) after the above code I get:

z: [[0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 4. 0. 0.]
 [0. 0. 0. 0. 0.]]

but when I use z later in my code I get:

    plt.contour(x[:,0], x[0,:], z.T,linewidths=0.5,colors='k',z=99)
TypeError: 'int' object is not subscriptable

my code seems to be breaking z somehow.

5
  • What is m.is_land? What are you trying to do? Commented Feb 13, 2018 at 21:29
  • @cᴏʟᴅsᴘᴇᴇᴅ I ask my map if this coordinate, i.e. xx,yy, is on land or not and it returns True or False. I then set the data at the corresponding position in z to 0 if it is water, otherwise I preserve the value Commented Feb 13, 2018 at 21:32
  • Okay, what is the problem with your current code? Commented Feb 13, 2018 at 21:33
  • @cᴏʟᴅsᴘᴇᴇᴅ Its distorting z somhow. Printing z before and after doesn't show any problems (some values have become 0.), but when I use z later in my code I get "TypeError: 'int' object is not subscriptable". If I comment out the code above then I don't get this error, so I must be damaging z in a manner I dont understand. Commented Feb 13, 2018 at 21:37
  • If it is setting more values of z, then you should check what m.is_land does. Commented Feb 13, 2018 at 21:42

1 Answer 1

1

To generate mask, you can use a list comprehension, then reshape the result and set the elements to z to 0 accordingly.

mask = np.reshape([
            m.is_land(i, j) for i, j in zip(x.ravel(), y.ravel())
       ], 
       z.shape
)

z[~mask] = 0
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks! Tried this with a 100*100 array and it took just a few seconds to compute, but with 500*500 it takes 3 minutes on my machine. Is this inevitable?
@Baz I think so. The problem is I cannot vectorize your m.is_land function because I don't know what it is doing.
@COLDSPEED is_land is a method within the matplotlib.Basemap class. You give it a lat/lng coordinate and it returns if this point is on land or not.
@Baz Okay. I don't think such a function is even going to be fast to begin with. What sizes are you typically working with?
@COLDSPEED 1000*1000 :). I think I might just have to solve this a different way by exporting the map to svg and manipulating it there.

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.