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]

 

Matplotlib UnidimensionalPlotagem bidimensional:

[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]

Matplotlib bidimensionalPlotagem tridimensional:

Para a visualização tridimensional utilizaremos outro pacote, o mayavi (http://github.enthought.com/mayavi/mayavi).

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

import numpy as np
from mayavi import mlab

grafico = mlab.surf(np.random.rand(30, 30))
mlab.colorbar(grafico, orientation='horizontal')
mlab.axes(grafico)

[/pastacode]

MayaVi 3DA janela mayavi que se abre é interativa: clicando no botão esquerdo do mouse, você pode girar a imagem, zoom com a roda do mouse, etc.

Indexando e cortando

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”]

a = np.arange(10)
a
a[0], a[2], a[-1]

[/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”]

a = np.diag(np.arange(3))
a
a[1, 1]
a[2, 1] = 10 # terceira linha, segunda coluna
a
a[1]

[/pastacode]

Note que:

  • Em 2D, a primeira dimensão corresponde as linhas e a segunda as colunas;
  • Para o array multidimensional a, a[0] é interpretado pegando-se todos os elementos da dimensão não especificada.

Arrays, como qualquer outra sequência em Python podem ser cortadas:

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

a = np.arange(10)
a
a[2:9:3] # [início:fim:incremento]

[/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”]

a[:4]

[/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”]

a[1:3]
a[::2]
a[3:]

[/pastacode]

Um pequeno resumo visual da indexação e corte de arrays do NumPy é ilustrado na figura abaixo.

Indexação NumPy 

Cópias e Visualizações

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”]

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

[/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”]

a = np.ones((4, 4))
a += a.T
a

[/pastacode]

Adicionando-se eixos

A indexação com o objeto np.newaxis permite adicionar um novo eixo ao array existente:

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

z = np.array([1, 2, 3])
z
z[:, np.newaxis]
z[np.newaxis, :]

[/pastacode]

Indexação sofisticada

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.

Usando máscaras booleanas

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

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

[/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”]

a[a
a

[/pastacode]

Utilizando uma array de inteiros

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

a = np.arange(10)
a

[/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”]

a[[2, 3, 2, 4, 2]]  # note: [2, 3, 2, 4, 2] é uma lista do Python

[/pastacode]

Novos valores pode ser atribuídos da seguinte maneira:

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

a[[9, 7]] = -10
a

[/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”]

a = np.arange(10)
idx = np.array([[3, 4], [9, 7]])
a[idx]

[/pastacode]

A imagem abaixo ilustra as diversas aplicações da indexação sofisticada:

Indexação Sofisticada NumPyPode-se ainda utilizar indexação sofisticada e broadcasting ao mesmo tempo:

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

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)]

[/pastacode]