0

I'm not sure what the correct terminology is here but I'm trying to mask out some values in a numpy array using multiple conditions from several arrays. For example, I want to find and mask out the areas in X where arrays t/l,lat2d,x, and m meet certain criteria. All the arrays are of the same shape: (250,500). I tried this:

cs[t < 274.0 | 
   l > 800.0 |
   lat2d > 60 |
   lat2d < -60 | 
   (x > 0 & m > 0.8) |
   (x < -25 & m < 0.2)] = np.nan

ufunc 'bitwise_and' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''.

I replaced the &,| with and/or and got the error:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

I've tried creating a mask: mask = t < 274.0 | l > 800.0 | lat2d > 60 | lat2d < -60 | (x > 0 & m > 0.8) | (x < -25 & m < 0.2), in order to use in a masked array but got the same error.

any idea how to do this in Python 3?

2
  • are the arrays l, t, m, x, lat2d fixed? Commented Mar 27, 2017 at 7:36
  • Yes, the arrays are fixed. Commented Mar 27, 2017 at 7:49

2 Answers 2

1

This is just a matter of operator precedence:

cs[(t < 274.0) | 
   (l > 800.0) |
   (lat2d > 60) |
   (lat2d < -60) |
   ((x > 0) & (m > 0.8)) |
   ((x < -25) & (m < 0.2))] = np.nan

should work

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

6 Comments

This is pretty neat!
So the parenthesis were the issue? Can you explain a bit more how your () are different than mine?
@Shejo284 I think it boils down to remembering the precedence rule PEMDAS in that order. So, using parenthesis will always make thing explicit and of higher precedence (i.e. it evaluates first)
The problem is that for certain technical reasons numpy abuses bitwise operators where in an ideal world logical operators would be used. These bitwise operators have higher operator precedence than their logical cousins, so for example without the additional parentheses your condition is interpreted like t < (274.0 | l) > (800.0 | ... which, of course, doesn't make much sense. For starters bitwise or is not defined on floats.
@PaulPanzer I see. Thanks for the solution and explanation. I'm a bit wiser today, pun intended :-)
|
0

You could do it using with a python function and then applying that function on the array.

def cond(x):
    if (np.all(t < 274.0) or np.all(l > 800.0) or np.all(lat2d > 60) or \
        np.all(lat2d < -60) or (np.all(x > 0) and np.all(m > 0.8)) or  \
        (np.all(x < -25) and np.all(m < 0.2))):
        return np.nan

Then apply this function on the array:

cs[:] = np.apply_along_axis(cond, 0, cs)

1 Comment

This is an interesting idea, but the other suggested solution works and with less coding. Appreciate the tips though :-)

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.