Luca
Luca

Reputation: 10996

removing entries from a numpy array

I have a multidimensional numpy array with the shape (4, 2000). Each column in the array is a 4D element where the first two elements represent 2D positions.

Now, I have an image mask with the same shape as an image which is binary and tells me which pixels are valid or invalid. An entry of 0 in the mask highlights pixels that are invalid.

Now, I would like to do is filter my first array based on this mask i.e. remove entries where the position elements in my first array correspond to invalid pixels in the image. This can be done by looking up the corresponding entries in the mask and marking those columns to be deleted which correspond to a 0 entry in the mask.

So, something like:

import numpy as np
# Let mask be a 2D array of 0 and 1s

array = np.random.rand(4, 2000)

for i in range(2000):
    current = array[:, i]
    if mask[current[0], current[1]] <= 0:
        # Somehow remove this entry from my array.

If possible, I would like to do this without looping as I have in my incomplete code.

Upvotes: 4

Views: 2061

Answers (2)

James Salmoni
James Salmoni

Reputation: 131

I'm not sure if I'm reading the question right. Let's try again!

You have an array with 2 dimensions and you want to remove all columns that have masked data. Again, apologies if I've read this wrong.

import numpy.ma as ma
a = ma.array((([[1,2,3,4,5],[6,7,8,9,10]]),mask=[[0,0,0,1,0],[0,0,1,0,0]])
a[:,-a.mask.any(0)] # this is where the action happens

the a.mask.any(0) identifies all columns that are masked into a Boolean array. It's negated (the '-' sign) because we want the inverse, and then it uses that array to remove all masked values via indexing.

This gives me an array:

[[1 2 5],[6 7 10]]

In other words, the array has all removed all columns with masked data anywhere. Hope I got it right this time.

Upvotes: 0

unutbu
unutbu

Reputation: 879201

You could select the x and y coordinates from array like this:

xarr, yarr = array[0, :], array[1, :]

Then form a boolean array of shape (2000,) which is True wherever the mask is 1:

idx = mask[xarr, yarr].astype(bool)

mask[xarr, yarr] is using so-called "integer array indexing". All it means here is that the ith element of idx equals mask[xarr[i], yarr[i]].

Then select those columns from array:

result = array[:, idx]

import numpy as np

mask = np.random.randint(2, size=(500,500))
array = np.random.randint(500, size=(4, 2000))

xarr, yarr = array[0, :], array[1, :]
idx = mask[xarr, yarr].astype(bool)
result = array[:, idx]

cols = []
for i in range(2000):
    current = array[:, i]
    if mask[current[0], current[1]] > 0:
        cols.append(i)
expected = array[:, cols]

assert np.allclose(result, expected)

Upvotes: 3

Related Questions