0

I have two NumPy arrays, say num and denom. I need to return specific values, based on if the respective elements are zero or not, in num and denom,

        r2 = []
        for denind, denel in enumerate(denom):
            numel = num[denind]
            if denel:  # Denominator is not zero
                r2.append(1 - numel/denom)
            elif numel:  # Denominator is zero, but numerator is not zero
                r2.append(0.0)
            else:  # Both denominator and numerator are zero.
                r2.append(1.0)
        return np.array(r2)

Is there a "NumPy" way of doing such an iteration.

1
  • Thanks for pointing that out. I've edited it, by the way, numel is used in the if numel condition. Commented Oct 9, 2013 at 14:33

3 Answers 3

2

Yes, you can use a boolean array as an index to fix up an array after your division. And you can use isinf(a) and isnan(a) to get the desired boolean arrays for indexing a.

with numpy.errstate(divide='ignore'):
    res = 1.0 - num/double(den);
res[isinf(res)] = 0.0;   # zero denominator will give +- infinity
res[isnan(res)] = 1.0;   # both zero will give nan

The magic here is that the boolean-array index returns a view into res which only selects those elements for which the boolean was True. If you read from that selection, you see a flat array, but if you write to it (as above) then it modifies the original array.

Also, I explicitly cast den to double because if both operands were integers there would by horror.

Update: It seems you should cast den, if you cast num it will still work, but you get a warning. Safest thing is to cast both.

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

10 Comments

Thanks, but it does give me a RuntimeWarning, that I have to catch.
In python 2.7, if num and den are integer it won't work (you get 0 instead of inf and nan. In python 3 you don't need the cast
you don't have to catch warnings. They just warn you and don't interrupt the execution. Of course you can catch it if you want. numpy.seterr should help you getting rid of the warning
Umm.. sorry, I had meant that I don't want the user to know there is a warning.
In Python2 I get no warning as long as I make sure that the argument is an array of doubles. @Fransesco how do numpy arrays behave in python3? Do they use the exact representation or does it automatically give you floating point?
|
1

How about doing the minimal amount of division work?

r2 = np.ones_like(numel, dtype=float)
num_mask = (numel != 0)
den_mask = (denel != 0)
mask = num_mask & den_mask
r2[mask] = 1 - numel[mask]/denel[mask]
mask = ~den_mask & num_mask
r2[mask] = 0

2 Comments

This seems really elegant to me. Is there any difference if I do, r2 = np.ones(numel.shape[1], dtype=float) in the first line?
No, but ones_like saves you having to extract the shape of the array manually.
1

You could use a nested np.where statement

numpy.where(denom !=0, 1 - numel/denom, np.where(numel != 0, 0, 1))

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.