O que é o numpy e o que são os objetos array
O Python possui:
- recipientes: listas, dicionários…;
- objetos numéricos de alto nível: inteiros, floats…
NumPy é:
- um pacote de extensão do Python para matrizes multi-dimensioais;
- próximo ao hardware (eficiência);
- desenvolvido para computação científica (conveniência).
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
import numpy as np
a = np.array([0, 1, 2, 3])
print a
[/pastacode]
Por exemplo:
Uma matriz contendo:
- valores de um experimento/simulação em tempos discretos;
- sinal gravado por um equipamento de medição, por exemplo, ondas sonoras;
- pixels de uma imagem, escala de cinza ou coloridos;
- dados tridimensionais medidos em posições X,Y,Z direfenres, por exemplo, MRI scan;
- entre outros…
Por que é muito útil: Recipiente eficiente na questão da memória que provê operações numéricas rápidas.
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
import time
import numpy as np
a = time.time()
L = range(1000000)
[i**2 for i in L]
print time.time() - a
a = time.time()
b = np.arange(1000000)
b**2
print time.time() - a
[/pastacode]
Documentação de referência
Na web: http://docs.scipy.org/
Ajuda interativa:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
help(np.array)
[/pastacode]
Procura por algo em específico:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
np.lookfor('create array')
[/pastacode]
Criando arrays
Unidimensionais:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
import numpy as np
a = np.array([0, 1, 2, 3])
a
a.ndim
a.shape
len(a)
[/pastacode]
Bidimensionais:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
b = np.array([[0, 1, 2], [3, 4, 5]]) # 2 x 3 array
b
b.ndim
b.shape
len(b)
[/pastacode]
Tridimensionais:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
c = np.array([[[1], [2]], [[3], [4]]])
c
c.shape
[/pastacode]
Na prática, raramente se entra com os itens um por um:
Espaçados igualmente:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
import numpy as np
a = np.arange(10) # 0 .. n-1
a
b = np.arange(1, 9, 2) # início, fim (exclusive), passo
b
[/pastacode]
Por número de pontos:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
c = np.linspace(0, 1, 6) # início, fim, número de pontos
c
d = np.linspace(0, 1, 5, endpoint=False)
d
[/pastacode]
Matrizes comuns:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
a = np.ones((3, 3)) # lembrete: (3, 3) é uma tupla
a
b = np.zeros((2, 2))
b
c = np.eye(3)
c
d = np.diag(np.array([1, 2, 3, 4]))
d
[/pastacode]
Números aleatórios:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
a = np.random.rand(4) # uniforme em [0, 1]
a
b = np.random.randn(4) # Gaussiana
b
np.random.seed(1234) # Definindo um início
[/pastacode]
Tipos básicos de dados
Você deve ter notado que, em alguns casos, os elementos de matriz são exibidos com um ponto final (por exemplo, 2. contra 2). Isto é devido a uma diferença no tipo de dados utilizada:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
a = np.array([1, 2, 3])
a.dtype
dtype('int64')
b = np.array([1., 2., 3.])
b.dtype
[/pastacode]
Diferentes tipos de dados nos permitem armazenar dados de forma mais compacta na memória, mas na maioria das vezes simplesmente trabalhamos com números de ponto flutuante. Note que, no exemplo acima, o NumPy detecta automaticamente o tipo de dados a partir da entrada.
Você pode especificar explicitamente o tipo de dado que você deseja:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
c = np.array([1, 2, 3], dtype=float)
c.dtype
[/pastacode]
O tipo de dado padrão é o ponto flutuante:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
a = np.ones((3, 3))
a.dtype
[/pastacode]
Também existem outros tipos:
Complexo:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
d = np.array([1+2j, 3+4j, 5+6*1j])
d.dtype
[/pastacode]
Booleano:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
e = np.array([True, False, False, True])
e.dtype
[/pastacode]
Strings:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
f = np.array(['Bonjour', 'Hello', 'Olá',])
f.dtype
[/pastacode]
Outros como int32 ou int64.
Visualização Básica
Agora que temos as matrizes dos dados, vamos, de maneira básica, visualizá-los.
Faremos isso utilizando o pyplot do matplotlib (que será visto com mais profundidade adiante).
O Matplotlib é um pacote de plotagem em 2D. Pode-se importar as funcionalidades do pyplot com o seguinte comando:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
import matplotlib.pyplot as plt #forma clássica
[/pastacode]
Plotagem unidimensional:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
import matplotlib.pyplot as plt
x = np.linspace(0, 3, 20)
y = np.linspace(0, 9, 20)
plt.plot(x, y) # plotagem da linha
plt.plot(x, y, 'o') # plotagem dos pontos
plt.show() # <-- mostra o gráfico
[/pastacode]
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
import matplotlib.pyplot as plt
image = np.random.rand(30, 30)
plt.imshow(image, cmap=plt.cm.jet)
plt.colorbar()
plt.show()
[/pastacode]
Para a visualização tridimensional utilizaremos outro pacote, o mayavi (http://github.enthought.com/mayavi/mayavi). [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] Os itens de um array (matriz) podem ser acessados e atribuídos da mesma forma que outras sequências do Python, como listas por exemplo. [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] ATENÇÃO: os índices também começam em zero no numpy. Para arrays multidimensionais, os índices são tuplas de inteiros: [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] Note que: Arrays, como qualquer outra sequência em Python podem ser cortadas: [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] Note que, assim como em qualquer sequência do Python, o último índice não é incluído: [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] Nenhum dos três componentes para o corte são necessários: por padrão, o início é 0, o final é o último e o incremento é 1: [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] Um pequeno resumo visual da indexação e corte de arrays do NumPy é ilustrado na figura abaixo. Uma operação de corte cria uma visualização do array original, a qual é apenas uma forma de se acessar dos dados da array. Assim, a matriz original não é copiada na memória. Quando modifica-se a visualização, a array original também é modificada: [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] Esse comportamento pode causar surpresa a primeira vista… mas ele permite economizar memoria e tempo. ATENÇÃO: a transposta é uma visualização. [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] A indexação com o objeto np.newaxis permite adicionar um novo eixo ao array existente: [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] Arrays NumPy podem ser trabalhadas com cortes, mas também com arrays booleanas ou de inteiros (máscaras). Esse método é conhecido como fancy indexing (indexação sofisticada). Ele cria copias e não visualizações. [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] Indexação com uma máscara pode ser muito útil para atribuir um novo valor a uma subarray: [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] A indexação pode ser feita com uma array de inteiros, onde o mesmo índice é repetido diversas vezes: [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] Novos valores pode ser atribuídos da seguinte maneira: [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] Quando um novo array é criado por indexação com um array de inteiros, o novo array possui a mesma forma do array de inteiros: [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] A imagem abaixo ilustra as diversas aplicações da indexação sofisticada: [pastacode lang=”python” message=”” highlight=”” provider=”manual”] [/pastacode] Plotagem tridimensional:
import numpy as np
from mayavi import mlab
grafico = mlab.surf(np.random.rand(30, 30))
mlab.colorbar(grafico, orientation='horizontal')
mlab.axes(grafico)
Indexando e cortando
a = np.arange(10)
a
a[0], a[2], a[-1]
a = np.diag(np.arange(3))
a
a[1, 1]
a[2, 1] = 10 # terceira linha, segunda coluna
a
a[1]
a = np.arange(10)
a
a[2:9:3] # [início:fim:incremento]
a[:4]
a[1:3]
a[::2]
a[3:]
Cópias e Visualizações
a = np.arange(10)
a
b = a[::2]; b
b[0] = 12
b
a
a = np.arange(10)
b = a[::2].copy() # forçar a cópia
b[0] = 12
a
a = np.ones((4, 4))
a += a.T
a
Adicionando-se eixos
z = np.array([1, 2, 3])
z
z[:, np.newaxis]
z[np.newaxis, :]
Indexação sofisticada
Usando máscaras booleanas
np.random.seed(3)
a = np.random.random_integers(0, 20, 15)
a
(a
mascara = (a
extrair_de_a = a[mascara] # ou, a[
extrair_de_a # extraída uma subarray com a máscara
a[a
a
Utilizando uma array de inteiros
a = np.arange(10)
a
a[[2, 3, 2, 4, 2]] # note: [2, 3, 2, 4, 2] é uma lista do Python
a[[9, 7]] = -10
a
a = np.arange(10)
idx = np.array([[3, 4], [9, 7]])
a[idx]
Pode-se ainda utilizar indexação sofisticada e broadcasting ao mesmo tempo:
a = np.arange(12).reshape(3,4)
a
i = np.array([[0, 1], [1, 2]])
a[i, 2] # mesmo que a[i, 2*np.ones((2, 2), dtype=int)]