1

In other words, does numpy support 'sieving'?

I have two arrays:

a = np.array([1, 0, 2, 3, 0, 4])
b = np.array([1, 0, 0, 0, 0, 6])

What I want is to return a new array, c, that contains the original values of a based on the mask of b:

c = a[b > 0] 
>> c
np.array([1, 4])
# but what I want is:
# np.array([1, 0, 0, 0, 0, 4])

I can get around this by doing a list comprehension:

c = [a[i] if b[i] > 0 else 0 for i in range(len(a))]

I could also make a mask, but that would require 2x iteration:

mask = [1 if b[i] > 0 else 0 for i in range(len(b))]  
c = ma.array(a, mask=mask)

Is there something native to numpy that allows one array to act like a sieve for another array?

1
  • How is a list comprehension "getting around". Is there something special you do not like about it? IMO it is the simplest and most readable solution. I would as well use zip just to make even more clear [a if b > 0 else 0 for a, b in zip(a,b)] . Commented Sep 26, 2019 at 17:46

2 Answers 2

2

Use np.where:

result = np.where(b > 0, a, 0)
print(result)

Or just multiply:

import numpy as np

a = np.array([1, 0, 2, 3, 0, 4])
b = np.array([1, 0, 0, 0, 0, 6])

print(a * (b > 0))

Output

[1 0 0 0 0 4]
Sign up to request clarification or add additional context in comments.

Comments

1

Another idea would be to initialize the result array c with zeroes (based on the shape of a) and then use a boolean mask to fill in the values from a. Below is an illustration:

# result array
In [28]: c = np.zeros_like(a)  

# get the indices where nonzero values exist in array `b`
In [29]: nonzero_idx = np.nonzero(b)  

# extract the corresponding values from the array `a` and
# fill in the array `c` using the same indices
In [30]: c[nonzero_idx] = a[nonzero_idx] 

In [31]: c 
Out[31]: array([1, 0, 0, 0, 0, 4])

The explanation for the case of using numpy.where:

In [42]: np.where(b >  0, *[a, 0])   
Out[42]: array([1, 0, 0, 0, 0, 4])

the part b > 0 is the condition that we're gonna check, with the entries in the array a. If this condition is satisfied, then those elements would be returned, else we a 0 would be returned; this is why we pass 0 as a third argument to numpy.where()

If you want some other values to be filled in instead of 0s, then pass the desired value. For example, let's say we want a -9 to be filled in the places where the condition (b > 0) is not satisfied (i.e. False), then we would write something like:

In [43]: np.where(b >  0, *[a, -9])     
Out[43]: array([ 1, -9, -9, -9, -9,  4])

Comments

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.