Perplexed by how to slice a numpy array

m is an ndarray with the form (12, 21, 21), now I want to take only a sparse fragment from it to form a new 2D array with

 sliceid = 0 indx = np.array([0, 2, 4, 6, 8, 10]) 

so sparse_slice intuitively

 sparse_slice = m[sliceid, indx, indx] 

but obviously this operation does not work, currently i'm using

 sparse_slice = m[sliceid,indx,:][:, indx] 

why doesn't the first โ€œintuitiveโ€ way work? and is there a more compact way than my current solution? all my previous ndarray slicing tests were based on nothing but intuition, maybe I will switch to read this serious guide ...

+4
source share
2 answers

A more compact way is new = m[0, :12:2, :12:2] . This is what numpy docs are called โ€œbasic indexing,โ€ which means you slice an integer or shear object (i.e. 0: 12: 2). When using basic indexing, numpy returns a representation of the original array. For instance:

 In [3]: a = np.zeros((2, 3, 4)) In [4]: b = a[0, 1, ::2] In [5]: b Out[5]: array([ 0., 0.]) In [6]: b[:] = 7 In [7]: a Out[7]: array([[[ 0., 0., 0., 0.], [ 7., 0., 7., 0.], [ 0., 0., 0., 0.]], [[ 0., 0., 0., 0.], [ 0., 0., 0., 0.], [ 0., 0., 0., 0.]]]) 

In your "intuitive" approach, what you are doing is indexing an array with another array. When you index a numpy array with another array, the arrays must be the same size (or they must be broadcast against each other, moreover, per second). In documents, this is called fancy indexing or advanced indexing. For instance:

 In [10]: a = np.arange(9).reshape(3,3) In [11]: a Out[11]: array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) In [12]: index = np.array([0,1,2]) In [13]: b = a[index, index] In [14]: b Out[14]: array([0, 4, 8]) 

You see that I get [0,0], [1,1] and [2,2] not a [0,0], a [0,1] ... If you want the "external product" of the index with an index you can do the following.

 In [22]: index1 = np.array([[0,0],[1,1]]) In [23]: index2 = np.array([[0,1],[0,1]]) In [24]: b = a[index1, index2] In [25]: b Out[25]: array([[0, 1], [3, 4]]) 

There is a summary for this:

 In [28]: index = np.array([0,1]) In [29]: index1, index2 = np.ix_(index, index) In [31]: index1 Out[31]: array([[0], [1]]) In [32]: index2 Out[32]: array([[0, 1]]) In [33]: a[index1, index2] Out[33]: array([[0, 1], [3, 4]]) In [34]: a[np.ix_(index, index)] Out[34]: array([[0, 1], [3, 4]]) 

You will notice that index1 is (2, 1) and index2 is (1, 2) , not (2, 2) . This is because the two arrays are passed to each other, you can learn more about the broadcast here . Keep in mind that when you use fantastic indexing, you get a copy of the source data, not a view. Sometimes itโ€™s better (if you want to leave the original data unchanged), and sometimes it just takes more memory. Read more about indexing here .

+5
source

If I am not mistaken, for the input m = np.array(range(5292)).reshape(12,21,21) you expect the output sparse_slice = m[sliceid,indx,:][:, indx]

 array([[ 0, 2, 4, 6, 8, 10], [ 42, 44, 46, 48, 50, 52], [ 84, 86, 88, 90, 92, 94], [126, 128, 130, 132, 134, 136], [168, 170, 172, 174, 176, 178], [210, 212, 214, 216, 218, 220]]) 

In this case, you can get it using the step slice part:

m[0, :12:2, :12:2]

+2
source

Source: https://habr.com/ru/post/1393896/


All Articles