0

So, I want to slice my 3d array to skip the first 2 arrays and then return the next two arrays. And I want the slice to keep following this pattern, alternating skipping 2 and giving 2 arrays etc.. I have found a solution, but I was wondering if there is a more elegant way to go about this? Preferably without having to reshape?

arr = np.arange(1, 251).reshape((10, 5, 5))
sliced_array = np.concatenate((arr[2::4], arr[3::4]), axis=1).ravel().reshape((4, 5, 5))
Tea
  • 87
  • 7
  • 1
    Try using this notation `arr[[2, 3, 6, 7], :, :]`. // You can supply lists of indices to pull from specific axes of matrices. Further, these lists only really need to be made up of integers and be within range. So you could provide the list `[2, 2, 1, 3, 3]` and get multiple copies of an axis and not necessarily in order either! – KDecker Jan 19 '23 at 15:24
  • Cool, I didn't know all that. I tried to make it a bit more generalized so that it can be any length: `slice = np.array([[i, i+1] for i in range(2, 10, 4)]).flatten()` and `sliced_array = arr[slice, :, :]`. Does that make sense? – Tea Jan 19 '23 at 15:36
  • 1
    `np.arange(10).reshape(5,2)[1::2]` should produce `[[2,3],[6,7]]` – hpaulj Jan 19 '23 at 16:33

2 Answers2

1

You can use boolean indexing using a mask that repeats [False, False, True, True, ...]:

import numpy as np

arr = np.arange(1, 251).reshape((10, 5, 5))
mask = np.arange(arr.shape[0]) % 4 >= 2

out = arr[mask]

out:

array([[[ 51,  52,  53,  54,  55],
        [ 56,  57,  58,  59,  60],
        [ 61,  62,  63,  64,  65],
        [ 66,  67,  68,  69,  70],
        [ 71,  72,  73,  74,  75]],

       [[ 76,  77,  78,  79,  80],
        [ 81,  82,  83,  84,  85],
        [ 86,  87,  88,  89,  90],
        [ 91,  92,  93,  94,  95],
        [ 96,  97,  98,  99, 100]],

       [[151, 152, 153, 154, 155],
        [156, 157, 158, 159, 160],
        [161, 162, 163, 164, 165],
        [166, 167, 168, 169, 170],
        [171, 172, 173, 174, 175]],

       [[176, 177, 178, 179, 180],
        [181, 182, 183, 184, 185],
        [186, 187, 188, 189, 190],
        [191, 192, 193, 194, 195],
        [196, 197, 198, 199, 200]]])
Chrysophylaxs
  • 5,818
  • 3
  • 10
  • 21
0

Since you want to select, and skip, the same numbers, reshaping works.

For a 1d array:

In [97]: np.arange(10).reshape(5,2)[1::2]
Out[97]: 
array([[2, 3],
       [6, 7]])

which can then be ravelled.

Generalizing to more dimensions:

In [98]: x = np.arange(100).reshape(10,10)    
In [99]: x.reshape(5,2,10)[1::2,...].reshape(-1,10)
Out[99]: 
array([[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
       [60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
       [70, 71, 72, 73, 74, 75, 76, 77, 78, 79]])

I won't go on to 3d because the display will be longer, but it should be straight forward.

hpaulj
  • 221,503
  • 14
  • 230
  • 353