Skip to content

    Chapter 8, Basic

    Indexing and slicing

    A good part of the work with arrays is to get exactly the piece you want: a value, a row, a column, a region.

    Code for this chapter: básico/cap08_indexacao.py

    One element, one row, one column

    In multi-dimensional arrays, you separate the indices of each axis by a comma, inside a single bracket: grade[linha, coluna]. The colons (:) mean "all elements of that axis":

    básico/cap08_indexacao.pylinhas 10 a 17
    import numpy as np
    
    grade = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    print(grade[1, 2])
    print(grade[:, 1])
    print(grade[0, ::-1])
    print(grade[1:, :2])
    print(grade[-1])
    
    Output
    6
    [2 5 8]
    [3 2 1]
    [[4 5]
     [7 8]]
    [7 8 9]
    

    The grade[1][2] also works, but creates an intermediate array (line 1) before getting the element, which is slower and less clear. Always prefer grade[1, 2].

    Slices: `start:end:step`

    As with lists, the end is excluded, negative indices count from the end, and the step can be negative. The difference is that, in the array, the slice can combine one axis at a time:

    básico/cap08_indexacao.pylinha 22
    print(np.arange(10)[::3])
    
    Output
    [0 3 6 9]
    

    Assigning to a slice

    A slice can receive a value (or another array), and the change happens in the original array. To prevent the example from altering the grid, I work on a copy:

    básico/cap08_indexacao.pylinhas 27 a 30
    copia = grade.copy()
    copia[0, :] = 0
    copia[:, 2] += 100
    print(copia)
    
    Output
    [[  0   0 100]
     [  4   5 106]
     [  7   8 109]]
    

    Three dimensions and the ellipsis

    In arrays of 3 or more dimensions, the ellipsis (...) means "all the axes I didn't mention". It is very useful for writing code that works in any number of dimensions:

    básico/cap08_indexacao.pylinhas 35 a 36
    cubo = np.arange(24).reshape(2, 3, 4)
    print(cubo[1, 2, 3], cubo[:, 0, :].shape, cubo[..., 0].shape)
    
    Output
    23 (2, 4) (2, 3)
    

    The cubo[..., 0] takes the first element of last axis, from all the others, and that's why the result has shape (2, 3).

    Index out of bounds

    Unlike slices, which are tolerant, an isolated index out of bounds raises an error, and the message specifies exactly which axis and what size:

    básico/cap08_indexacao.pylinhas 41 a 44
    try:
        grade[5]
    except IndexError as erro:
        print(erro)
    
    Output
    index 5 is out of bounds for axis 0 with size 3
    

    A slice is a view, not a copy

    Unlike Python lists, a slice of an array does not copy the data. It is a "window" to the same memory, and changing the slice changes the original. Chapter 10 is entirely about this, and it is what surprises most those coming from lists.

    Exercise 1

    The core of a matrix

    Write centro(a) that returns the matrix without the borders (without the first and last row and column). For np.arange(16).reshape(4, 4), the result is [[5, 6], [9, 10]].