Caroline.py
Caroline.py

Reputation: 313

Python advanced slicing

I am a little confused with Python's advanced slicing. I basically had a dictionary and with help from SO, I made it into an array.

   array1 = 
   ([[[36, 16],
    [48, 24],
    [12,  4],
    [12,  4]],

   [[48, 24],
    [64, 36],
    [16,  6],
    [16,  6]],

   [[12,  4],
    [16,  6],
    [ 4,  1],
    [ 4,  1]],

   [[12,  4],
    [16,  6],
    [ 4,  1],
    [ 4,  1]]])

To practice using matrix solver, the array was turned into a square matrix (4 x 4) using:

 array_matrix_sized = array[:, :, 0] 

I read that this means [number of indices, rows, columns]. I am a little clueless as to why [:,:,0] returns a 4 x 4 matrix. To try to help, I made an array that has a length 100, and I have been trying to turn it into a 10 x 10 matrix in a similar manner with no success. What throws me off is the number of rows is ":" and the number of columns is "0", if I read this concept correctly. For a 4 x 4 matrix, why isn't it array[:, 4, 4]? I am also assuming the : is because I am interested in all the values.

Thank you in advance for any help/advice. I do apologize if this is a simple question, but I really could use the clarification on how this works.

Still not quite understanding. If I have

 array2 = array([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,
    13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,
    26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
    39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  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, 101, 102, 103,
   104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
   117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
   130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
   143, 144, 145, 146, 147, 148, 149, 150, 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])

To get it into a 10 X 10 matrix, I tried using array2[:,:,0] and get the error IndexError: too many indices for array. Isn't this similar to my first example?

Upvotes: 2

Views: 7253

Answers (4)

Rameez Ahmad Dar
Rameez Ahmad Dar

Reputation: 871

code s=np.arange(Total no. of matrices * number of rows * number of columns).reshape(Total no. of matrices * number of rows * number of columns).Example if code is rameez=np.arange(5*4*4).reshape(5,4,4) [[5=Total no of matrices to be generated]].[[4*4 is the 4*4 dimensional matrix]].Here we will get 5 matrices each of which is 4*4 dimensional matrix.Code rameez=np.arange(10*3*2).reshape(10,3,2) will generate 10 matrices as a whole each with the ((3 * 2)) dimensions.

Upvotes: 0

NaN
NaN

Reputation: 2332

The book analogy is good, but I tend to arrange my arrays in a slightly different order. If we consider the following data array...

a = np.arange(2*3*4).reshape(2,3,4)
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])

To me, the above reads as 2 pages, one above the other. Each page has 3 rows and there are 4 words in each row.

I wrote a function to take the same information and arrange it side-by-side since this is the way I tend to arrange things I am working on. (details aren't relevant here...). Here is the rearrangement for visual purposes...

a = np.arange(2*3*4).reshape(2,3,4)

Array... shape (2, 3, 4), ndim 3, not masked
  0,  1,  2,  3    12, 13, 14, 15   
  4,  5,  6,  7    16, 17, 18, 19   
  8,  9, 10, 11    20, 21, 22, 23   
 sub (0)           sub (1)    

a[0,:,:]
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

a[:,0,:]
array([[ 0,  1,  2,  3],
       [12, 13, 14, 15]])

>>> a[:,:,0]
array([[ 0,  4,  8],
       [12, 16, 20]])

So in my case the sequence from a[0,:,:], a[:,0,:] to a[:,:,0] follows the sequence page, row and word.

People can argue from a different perspective, but I think it is important to realize that not all people view things the same way. I often work with images I prefer the above arrangement of (image, row, column) which is equivalent to the (page, row, word) notation.

Do note... if you don't like the way an array looks, or it doesn't work for you... just swap axes.

a.swapaxes(2,0)
array([[[ 0, 12],
        [ 4, 16],
        [ 8, 20]],

       [[ 1, 13],
        [ 5, 17],
        [ 9, 21]],

       [[ 2, 14],
        [ 6, 18],
        [10, 22]],

       [[ 3, 15],
        [ 7, 19],
        [11, 23]]])

Still not feeling it?... try a different arrangement until it clicks or simplifies your calculations.

Upvotes: 0

juanpa.arrivillaga
juanpa.arrivillaga

Reputation: 96349

I just wanted to add a clarifying example:

>>> np.arange(4*4*2).reshape(4,4,2)
array([[[ 0,  1],
        [ 2,  3],
        [ 4,  5],
        [ 6,  7]],

       [[ 8,  9],
        [10, 11],
        [12, 13],
        [14, 15]],

       [[16, 17],
        [18, 19],
        [20, 21],
        [22, 23]],

       [[24, 25],
        [26, 27],
        [28, 29],
        [30, 31]]])

Since we are in three dimensions, we can still maintain a spatial metaphor. Imagine these 4X2 slices were all stacked up against each other, in front of you, in order (like if they were books). That is, we take the first one and prop it up like a book, the second one behind it and so forth. We choose the first chunk from the first dimension, and it merely gives us back the first "book":

>>> a[0,:,:]
array([[0, 1],
       [2, 3],
       [4, 5],
       [6, 7]])

Now look at the difference between that and the first chunk of the second dimension:

>>> a[:,0,:]
array([[ 0,  1],
       [ 8,  9],
       [16, 17],
       [24, 25]])

This is like slicing off the top. Imagine shaving off the top. It just so happens that with the array you posted, these are the same!

Now finally, the first chunk of the third dimension:

>>> a[:,:,0]
array([[ 0,  2,  4,  6],
       [ 8, 10, 12, 14],
       [16, 18, 20, 22],
       [24, 26, 28, 30]])

This is like slicing what you have in front of you in half - imagine a karate-chop.

Here's a (very crude) image (drawn on my laptop...sorry). enter image description here

Upvotes: 3

BrenBarn
BrenBarn

Reputation: 251598

I read that this means [number of indices, rows, columns]. [...] What throws me off is the number of rows is ":" and the number of columns is "0", if I read this concept correctly.

No. It means [which parts I want on dimension 1, which parts I want on dimension 2, which parts I want on dimension 3]. The indices are not how many rows/columns you want, they are which ones you want. And, as you said : means "all" in this context.

For a 4 x 4 matrix, why isn't it array[:, 4, 4]?

You don't specify the shape of the result. The shape of the result depends on the shape of the original array. Since your array is 4x4x2, getting one element on the last dimension gives you 4x4. If the array was 8x7x2, then [:, :, 0] would give you an 8x7 result.

So [:, :, 0] means "give me everything on the first two dimensions, but only the first item on the last dimension. This amounts to getting the first element of each "row" (or the first "column" as it appears in the display) which is why you get the result you get:

>>> array1[:, :, 0]
array([[36, 48, 12, 12],
       [48, 64, 16, 16],
       [12, 16,  4,  4],
       [12, 16,  4,  4]])

Likewise, doing [0, :, :] gives you the first "chunk":

>>> array1[0, :, :]
array([[36, 16],
       [48, 24],
       [12,  4],
       [12,  4]])

And doing [:, 0, :] gives you the first row of each chunk:

>>> x[:, 0, :]
array([[36, 16],
       [48, 24],
       [12,  4],
       [12,  4]])

Upvotes: 4

Related Questions