idem
idem

Reputation: 155

setting null values in a numpy array

how do I null certain values in numpy array based on a condition? I don't understand why I end up with 0 instead of null or empty values where the condition is not met... b is a numpy array populated with 0 and 1 values, c is another fully populated numpy array. All arrays are 71x71x166

a = np.empty(((71,71,166)))
d = np.empty(((71,71,166)))
for indexes, value in np.ndenumerate(b):
    i,j,k = indexes
    a[i,j,k] = np.where(b[i,j,k] == 1, c[i,j,k], d[i,j,k])

I want to end up with an array which only has values where the condition is met and is empty everywhere else but with out changing its shape

FULL ISSUE FOR CLARIFICATION as asked for:
I start with a float populated array with shape (71,71,166)
I make an int array based on a cutoff applied to the float array basically creating a number of bins, roughly marking out 10 areas within the array with 0 values in between
What I want to end up with is an array with shape (71,71,166) which has the average values in a particular array direction (assuming vertical direction, if you think of a 3D array as a 3D cube) of a certain "bin"...
so I was trying to loop through the "bins" b == 1, b == 2 etc, sampling the float where that condition is met but being null elsewhere so I can take the average, and then recombine into one array at the end of the loop....
Not sure if I'm making myself understood. I'm using the np.where and using the indexing as I keep getting errors when I try and do it without although it feels very inefficient.

Upvotes: 11

Views: 93158

Answers (2)

jmilloy
jmilloy

Reputation: 8365

Consider this example:

import numpy as np
data = np.random.random((4,3))
mask = np.random.random_integers(0,1,(4,3))
data[mask==0] = np.NaN

The data will be set to nan wherever the mask is 0. You can use any kind of condition you want, of course, or do something different for different values in b.

To erase everything except a specific bin, try the following:

c[b!=1] = np.NaN

So, to make a copy of everything in a specific bin:

a = np.copy(c)
a[b!=1] == np.NaN

To get the average of everything in a bin:

np.mean(c[b==1])

So perhaps this might do what you want (where bins is a list of bin values):

a = np.empty(c.shape)
a[b==0] = np.NaN
for bin in bins:
    a[b==bin] = np.mean(c[b==bin])

Upvotes: 11

user707650
user707650

Reputation:

np.empty sometimes fills the array with 0's; it's undefined what the contents of an empty() array is, so 0 is perfectly valid. For example, try this instead:

d = np.nan * np.empty((71, 71, 166)).

But consider using numpy's strength, and don't iterate over the array:

a = np.where(b, c, d)

(since b is 0 or 1, I've excluded the explicit comparison b == 1.)

You may even want to consider using a masked array instead:

a = np.ma.masked_where(b, c)

which seems to make more sense with respect to your question: "how do I null certain values in a numpy array based on a condition" (replace null with mask and you're done).

Upvotes: 4

Related Questions