10

I have a given numpy array and a list containing a number of slice objects (alternatively containing (start, end) tuples). I am looking to remove the slice object positions from the original array and get a second array with the remaining values.

Toy example:

myarray = np.arange(20)

array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19])

mylist=(slice(2,4),slice(15,19))

Do something and result should be

array([0, 1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])

The array can be in a few hundred thousand large, the list of slice objects can contain a few thousand elements and I need to run the operation often, so speed is somewhat important.

Numpy delete does not take a list of slices as far I can see?

For now I am generating the complement of my slice object list and slicing that, but generating the complement is a somewhat awkward process where I am sorting my slice list then iterating through it, creating the complement slice objects as needed. I am hoping there is a more elegant way I have not figured!

3 Answers 3

3

You can use np.r_[] to join the slices into an array:

myarray = np.arange(20)
mylist=(slice(2, 4),slice(15, 19))
np.delete(myarray, np.r_[tuple(mylist)])

output:

array([ 0,  1,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 19])

But I think it's not very fast.

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

Comments

1

You can use set() to identify which positions will be kept and np.take() to obtain the corresponding values, doing something like:

ind = np.indices(myarray.shape)[0]
rm = np.hstack([ind[i] for i in mylist])

ans = np.take(myarray, sorted(set(ind)-set(rm)))

Note that np.hstack() is used to obtain a single array with all the indices that will be removed. This takes about half the time of @HYRY's solution.

Comments

1

I can't think of a way to join the slices cleanly; however, I think using the composite is the way to go. Perhaps try something like this:

import numpy as np

# Create test data
n_data = 1000000
n_slices = 10000

data = np.arange(n_data)
slices = []
for i in range(n_slices):
    r = np.random.randint(n_data-1000)
    slices.append(slice(r,r + np.random.randint(1000)))

# Remove slices
keep_mask = np.ones_like(data, dtype=bool)
for slice in slices: keep_mask[slice] = False
data = data[keep_mask] # or np.take, etc.

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.