Spenhouet
Spenhouet

Reputation: 7169

Slice every item except every nth

In tensorflow it is possible to select every nth item with the slicing notation [::n].

But how to do the opposite? I want to select every item except every nth.

For example:

a = [1, 2, 3, 4, 5, 6, 7, 8]

a[2::3] would result in [3, 6]

Now I would like to have the opposite: [1, 2, 4, 5, 7, 8]

The array above is just an example. A solution should work for bigger matrices of the dimension [batch, width, height, channels] in tensorflow. The selection is only done on the channels. Also my matrix contains real values that are non unique. I will also not be able to reshape it further down than to two dimensions ( [batch, channels] )

Upvotes: 4

Views: 2441

Answers (3)

kmario23
kmario23

Reputation: 61335

A plain application of numpy.setdiff1d() will work for 1D arrays of int dtype.

In [16]: arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])

In [17]: np.setdiff1d(arr, arr[2::3])
Out[17]: array([1, 2, 4, 5, 7, 8])

The corresponding TensorFlow equivalent is tf.setdiff1d()


To handle nD arrays (i.e. tensors), you can first reshape them to 1D arrays, do the selection using setdiff1d and then reshape the result back to nD.

Upvotes: 1

akuiper
akuiper

Reputation: 214957

One option is to create a boolean index by testing the a range index:

import numpy as np
start, step = 2, 3
a[np.arange(len(a)) % step != start]
# array([1, 2, 4, 5, 7, 8])

You can achieve this similarly in tensorflow using tf.boolean_mask:

import tensorflow as tf

a = tf.constant([1, 2, 3, 4, 5, 6, 7, 8])

start, step = 2, 3
mask = ~tf.equal(tf.range(a.shape[-1]) % step, start)

tf.boolean_mask(a, mask).eval()
# array([1, 2, 4, 5, 7, 8], dtype=int32)

If a is ND tensor, you can specify the axis with boolean_mask; with 4D tensor [batch, width, height, channels] for instance, to select by the fourth axis, i.e the channels, you can set axis=3:

mask = ~tf.equal(tf.range(a.shape[-1]) % step, start)
tf.boolean_mask(a, mask, axis=3)

Upvotes: 7

Daniel Labbe
Daniel Labbe

Reputation: 2019

You can use the np.delete() method:

>>> np.delete(a, a[1::3])
array([1, 2, 4, 5, 7, 8])

Remembering that this operation does not modify the original array:

Return a new array with sub-arrays along an axis deleted. For a one dimensional array, this returns those entries not returned by arr[obj].

Upvotes: 1

Related Questions