Pular para o conteúdo

    Capítulo 8, Básico

    Indexação e fatiamento

    Boa parte do trabalho com arrays é pegar exatamente o pedaço que você quer: um valor, uma linha, uma coluna, uma região.

    Código deste capítulo: básico/cap08_indexacao.py

    Um elemento, uma linha, uma coluna

    Em arrays de várias dimensões, você separa os índices de cada eixo por vírgula, dentro de um único colchete: grade[linha, coluna]. Os dois pontos (:) significam "todos os elementos desse eixo":

    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])
    
    Saída
    6
    [2 5 8]
    [3 2 1]
    [[4 5]
     [7 8]]
    [7 8 9]
    

    O grade[1][2] também funciona, mas cria um array intermediário (a linha 1) antes de pegar o elemento, o que é mais lento e menos claro. Prefira sempre grade[1, 2].

    Fatias: `inicio:fim:passo`

    Como nas listas, o fim é excluído, os índices negativos contam do fim e o passo pode ser negativo. A diferença é que, no array, a fatia pode combinar um eixo por vez:

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

    Atribuir a uma fatia

    Uma fatia pode receber um valor (ou outro array), e a mudança acontece no array original. Para o exemplo não alterar a grade, eu trabalho em uma cópia:

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

    Três dimensões e a reticência

    Em arrays de 3 ou mais dimensões, a reticência (...) significa "todos os eixos que eu não mencionei". É muito útil para escrever código que funciona em qualquer número de dimensões:

    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)
    
    Saída
    23 (2, 4) (2, 3)
    

    O cubo[..., 0] pega o primeiro elemento do último eixo, de todos os outros, e por isso o resultado tem forma (2, 3).

    Índice fora dos limites

    Diferente das fatias, que são tolerantes, um índice isolado fora do limite levanta erro, e a mensagem diz exatamente qual eixo e qual tamanho:

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

    Uma fatia é uma visão, não uma cópia

    Ao contrário das listas do Python, a fatia de um array não copia os dados. Ela é uma "janela" para a mesma memória, e alterar a fatia altera o original. O capítulo 10 é inteiro sobre isso, e é o que mais surpreende quem vem das listas.

    Exercício 1

    O miolo de uma matriz

    Escreva centro(a) que devolva a matriz sem as bordas (sem a primeira e a última linha e coluna). Para np.arange(16).reshape(4, 4), o resultado é [[5, 6], [9, 10]].