Operações elemento a elemento

Com escalares:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.array([1, 2, 3, 4])
a + 1
2**a

[/pastacode]

Todas operações aritiméticas operam elemento a elemento:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

b = np.ones(4) + 1
a - b
a * b
j = np.arange(5)
2**(j + 1) - j

[/pastacode]

ATENÇÃO: Multiplicação de array não é multiplicação de matrizes.

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

c = np.ones((3, 3))
c * c

[/pastacode]

Multiplicação de matrizes:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

c.dot(c)

[/pastacode]

Comparações:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.array([1, 2, 3, 4])
b = np.array([4, 2, 2, 4])
a == b
a > b

[/pastacode]

Operações lógicas:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.array([1, 1, 0, 0], dtype=bool)
b = np.array([1, 0, 1, 0], dtype=bool)
np.logical_or(a, b)
np.logical_and(a, b)

[/pastacode]

Incompatibilidade de forma:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.arange(4)
a + np.array([1, 2])

[/pastacode]

Transposição:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.triu(np.ones((3, 3)), 1)   # veja help(np.triu)
a
a.T

[/pastacode]

Álgebra linear:

O submódulo numpy.linalg implementa a Àlgebra Linear básica, como a resolição de sistemas lineares, decomposição de valores singulares, etc. No entanto, não é garantida que seja compilada utilizando rotinas eficientes e portanto é recomendável a utilização do scipy.linalg, como será detalhado mais adiante.

Reduções Básicas

Computando somas:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

x = np.array([1, 2, 3, 4])
np.sum(x)
x.sum()

[/pastacode]

Soma por linha e por coluna:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

x = np.array([[1, 1], [2, 2]])
x
x.sum(axis=0)   # colunas (primeira dimensão)
x[:, 0].sum(), x[:, 1].sum()
x.sum(axis=1)   # linhas (segunda dimensão)
x[0, :].sum(), x[1, :].sum()

[/pastacode]

A ideia é a mesma em maiores dimensões:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

x = np.random.rand(2, 2, 2)
x.sum(axis=2)[0, 1]     
x[0, 1, :].sum()

[/pastacode]

Outras reduções

Funcionam da mesma forma (e usam axes=)

  • Estatística:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

x = np.array([1, 2, 3, 1])
y = np.array([[1, 2, 3], [5, 6, 1]])
x.mean()
np.median(x)
np.median(y, axis=-1) # último eixo
x.std()          # desvio padrão com população total

[/pastacode]

  • Extremos:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

x = np.array([1, 3, 2])
x.min()
x.max()
x.argmin()  # índice do mínimo
x.argmax()  # índice do máximo

[/pastacode]

  • Operações lógicas:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

np.all([True, True, False])
np.any([True, True, False])

[/pastacode]

Pode ser utilizada para comparações de arrays:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.zeros((100, 100))
np.any(a != 0)
np.all(a == a)
a = np.array([1, 2, 3, 2])
b = np.array([2, 2, 3, 2])
c = np.array([6, 4, 4, 5])
((a <= b) & (b <= c)).all()

[/pastacode]

  • E muito mais… (melhor aprender conforme a necessidade).

Broadcasting

  • As operações básicas nas arrays do NumPy são elemento a elemento;
  • Essas operações só funcionam em arrays de mesmo tamanho, no entanto, é possível fazer operações em arrays de diferentes tamanhos se o NumPy puder transformá-las para que todas tenham o mesmo tamanho: essa convenção é chamada de Broadcasting.

A imagem abaixo dá um exemplo de broadcasting:

Numpy BroadcastingVamos verificar:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.tile(np.arange(0, 40, 10), (3, 1)).T
a
b = np.array([0, 1, 2])
a + b

[/pastacode]

Um truque útil:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.arange(0, 40, 10)
a.shape
a = a[:, np.newaxis]  # adiciona um novo eixo -> array 2D
a.shape
a
a + b

[/pastacode]

Ou seja, acabamos de utilizar o broadcasting sem saber:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.ones((4, 5))
a[0] = 2  # atribuimos uma array de dimensão 0 a uma array de dimensão 1
a

[/pastacode]

Broadcasting parece ser um pouco mágico, mas na verdade é bem natural utilizá-lo quando se deseja resolver um problema no qual os dados de saída são uma array com mais dimensões que os dados de entrada.

Vários problemas do tipo grid-based ou netword-bases podem também utilizar broadcasting. Por exemplo, se desejarmos calcular a distância da origem aos pontos em um grid de 10×10, podemos fazer:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

x, y = np.arange(5), np.arange(5)
distance = np.sqrt(x ** 2 + y[:, np.newaxis] ** 2)
distance

[/pastacode]

Ou, em cores:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

plt.pcolor(distance)    
plt.colorbar()

[/pastacode]

Detalhe: a função numpy.pgrid permite criar diretamento vetores x e y do exemplo anterior com duas “dimensões significativas”.

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

x, y = np.ogrid[0:5, 0:5]
x, y
x.shape, y.shape
distance = np.sqrt(x ** 2 + y ** 2)

[/pastacode]

Então, o np.ogrid é muito útil quando precisarmos lidar com computação de dados em grids. Por outro lado, np.mgrid oferece matrizes cheias de índices para os casos os não quisermos ou não pudermos nos beneficiar do broadcasting:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

x, y = np.mgrid[0:4, 0:4]
x
y

[/pastacode]

Na prática é muito pouco utilizado.

Manipulação de forma do array

Achatamento (flattening):

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.array([[1, 2, 3], [4, 5, 6]])
a.ravel()
a.T
a.T.ravel()

[/pastacode]

Dimensões altas: últimas dimensões se desfazem primeiro

Remodelagem (reshaping):

Operação inversa ao achatamento:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a.shape
b = a.ravel()
b
b.reshape((2, 3))

[/pastacode]

Criando um array de forma diferente com outro array:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.arange(36)
b = a.reshape((6, 6))
b

[/pastacode]

ou:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

b = a.reshape((6, -1))

[/pastacode]

Visualizações e cópias

ndarray.reshape pode retornar uma visualização e não uma cópia:

b[0, 0] = 99

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a

[/pastacode]

Cuidado: a remodelagem pode também retornar uma cópia!

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.zeros((3, 2))
b = a.T.reshape(3*2)
b[0] = 9
a

[/pastacode]

Embaralhamento da dimensão

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.arange(4*3*2).reshape(4, 3, 2)
a.shape
a[0, 2, 1]
b = a.transpose(1, 2, 0)
b.shape
b[2, 1, 0]

[/pastacode]

Também cria uma visualização:

b[2, 1, 0] = -1
a[0, 2, 1]

Redimensionamento

O tamanho de um array pode ser modificado com ndarray.resize:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.arange(4)
a.resize((8,))
a

[/pastacode]

No entanto, não deve estar referenciado a algo mais:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

b = a
a.resize((4,))

[/pastacode]

Ordenando dados

Ordenando em um eixo:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.array([[4, 3, 5], [1, 2, 1]])
b = np.sort(a, axis=1)
b

[/pastacode]

Nota: ordena cada linha separadamente.

Ordenação no lugar:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a.sort(axis=1)
a

[/pastacode]

Ordenação com indexação sofisticada:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.array([4, 3, 1, 2])
j = np.argsort(a)
j
a[j]

[/pastacode]

Encontrando os máximos e mínimos:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a = np.array([4, 3, 1, 2])
j_max = np.argmax(a)
j_min = np.argmin(a)
j_max, j_min

[/pastacode]

Sumário

O que é preciso saber para começcar:

  • Criar arrays com array, arange, ones, zeros.
  • Saber a forma do array com array.shape, então cortá-la para obter diferentes visualizações array[::2], etc.
  • Ajustar a forma do array usando reshape ou achatá-la utilizando o ravel.
  • Obter um subconjunto dos elementos de um array e/ou modificar seus valores com máscaras:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a[a < 0] = 0

[/pastacode]

  • Conhecer diversas operações sobre arrays, como encontrar a média ou o máximo (array.max(), array.mean()).

Não há a necessidade de se decorar tudo, mas deve-se saber como buscar no help ou na documentação online.