NumPy

Para lidarmos com matrizes e vetores, e realizar operações matemáticas nesses objetos, usamos a biblioteca NumPy e um formato de dados específico: a numpy-array, ou ndarray, que é uma estrutura de dados homogêneos multidimensional, que é uma tabela de elementos (em geral, números), todos do mesmo tipo, indexados por uma tupla de inteiros positivos. As dimensões são chamadas de eixos, e o número de eixos é o rank. Por exemplo, um vetor tem rank 1; uma matriz (não importa de que tamanho) tem rank 2.


In [1]:
import numpy as np
A = np.zeros((10,10))

In [2]:
print(A)


[[ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]

Atenção: Note que numpy.array não é o mesmo que a classe padrão do Python array.array, que lida apenas com vetores unidimensionais e oferece muito menos funcionalidades.


In [3]:
A = np.matrix([[10,3],[1,2],[3,1]])

In [4]:
print(A)


[[10  3]
 [ 1  2]
 [ 3  1]]

In [5]:
lista = [1,2,3,4]
np.asarray(lista)


Out[5]:
array([1, 2, 3, 4])

In [6]:
dir(A)


Out[6]:
['A',
 'A1',
 'H',
 'I',
 'T',
 '__abs__',
 '__add__',
 '__and__',
 '__array__',
 '__array_finalize__',
 '__array_interface__',
 '__array_prepare__',
 '__array_priority__',
 '__array_struct__',
 '__array_wrap__',
 '__bool__',
 '__class__',
 '__contains__',
 '__copy__',
 '__deepcopy__',
 '__delattr__',
 '__delitem__',
 '__dict__',
 '__dir__',
 '__divmod__',
 '__doc__',
 '__eq__',
 '__float__',
 '__floordiv__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__gt__',
 '__hash__',
 '__iadd__',
 '__iand__',
 '__ifloordiv__',
 '__ilshift__',
 '__imatmul__',
 '__imod__',
 '__imul__',
 '__index__',
 '__init__',
 '__int__',
 '__invert__',
 '__ior__',
 '__ipow__',
 '__irshift__',
 '__isub__',
 '__iter__',
 '__itruediv__',
 '__ixor__',
 '__le__',
 '__len__',
 '__lshift__',
 '__lt__',
 '__matmul__',
 '__mod__',
 '__module__',
 '__mul__',
 '__ne__',
 '__neg__',
 '__new__',
 '__or__',
 '__pos__',
 '__pow__',
 '__radd__',
 '__rand__',
 '__rdivmod__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__rfloordiv__',
 '__rlshift__',
 '__rmatmul__',
 '__rmod__',
 '__rmul__',
 '__ror__',
 '__rpow__',
 '__rrshift__',
 '__rshift__',
 '__rsub__',
 '__rtruediv__',
 '__rxor__',
 '__setattr__',
 '__setitem__',
 '__setstate__',
 '__sizeof__',
 '__str__',
 '__sub__',
 '__subclasshook__',
 '__truediv__',
 '__xor__',
 '_align',
 '_collapse',
 '_getitem',
 'all',
 'any',
 'argmax',
 'argmin',
 'argpartition',
 'argsort',
 'astype',
 'base',
 'byteswap',
 'choose',
 'clip',
 'compress',
 'conj',
 'conjugate',
 'copy',
 'ctypes',
 'cumprod',
 'cumsum',
 'data',
 'diagonal',
 'dot',
 'dtype',
 'dump',
 'dumps',
 'fill',
 'flags',
 'flat',
 'flatten',
 'getA',
 'getA1',
 'getH',
 'getI',
 'getT',
 'getfield',
 'imag',
 'item',
 'itemset',
 'itemsize',
 'max',
 'mean',
 'min',
 'nbytes',
 'ndim',
 'newbyteorder',
 'nonzero',
 'partition',
 'prod',
 'ptp',
 'put',
 'ravel',
 'real',
 'repeat',
 'reshape',
 'resize',
 'round',
 'searchsorted',
 'setfield',
 'setflags',
 'shape',
 'size',
 'sort',
 'squeeze',
 'std',
 'strides',
 'sum',
 'swapaxes',
 'take',
 'tobytes',
 'tofile',
 'tolist',
 'tostring',
 'trace',
 'transpose',
 'var',
 'view']

In [7]:
print("Matriz: ",A)
print("Diagonal: ", A.diagonal())


Matriz:  [[10  3]
 [ 1  2]
 [ 3  1]]
Diagonal:  [[10  2]]

Alguns conceitos são um pouco diferentes no numpy (em relação ao MATLAB). Cuidado:


In [8]:
np.size(A)


Out[8]:
6

In [9]:
np.shape(A)


Out[9]:
(3, 2)

In [10]:
np.ndim(A)


Out[10]:
2

Com o numpy, é possível efetuar operações vetoriais, similarmente ao que ocorre no MATLAB, mas a sintaxe pode ser diferente. Cuidado com as pegadinhas, por exemplo:


In [11]:
A = np.array([[1,2],[3,4]])
B = np.array([[5,6],[7,8]])

A*B


Out[11]:
array([[ 5, 12],
       [21, 32]])

Para efetuar a multiplicação entre matrizes como estamos acostumados, usamos


In [12]:
np.dot(A,B)


Out[12]:
array([[19, 22],
       [43, 50]])

In [13]:
np.transpose(A)


Out[13]:
array([[1, 3],
       [2, 4]])

Observação: namespaces

Talvez você já tenha percebido que ao executarmos comandos, nos referimos ao módulo em que o comando está definido. Por exemplo, para usar a função transpose do módulo numpy, que importamos como np, usamos o comando

np.transpose(A)

isso significa que a função transpose que estamos utilizando "mora" dentro do módulo numpy.

Exemplo:


In [14]:
import math
import numpy
import scipy

print(math.pi, "do módulo math")
print(numpy.pi, "do módulo numpy")
print(scipy.pi, "do módulo scipy")


3.141592653589793 do módulo math
3.141592653589793 do módulo numpy
3.141592653589793 do módulo scipy

In [15]:
import math as matematica

In [16]:
matematica.pi


Out[16]:
3.141592653589793

In [17]:
import math as biblioteca

In [18]:
biblioteca.pi


Out[18]:
3.141592653589793

matplotlib

A biblioteca matplotlib, e em particular seu módulo matplotlib.pyplot, permites ao usuário fazer gráficos com uma sintaxe parecida com o que é feito no MATLAB.

Cada função executa uma ação em uma figura. Por exemplo, para fazer um gráfico simples, usamos algo do tipo


In [19]:
import matplotlib.pyplot as plt
plt.plot([1,2,3,4])
plt.ylabel('meus números')
plt.show()


Como queremos que os gráficos fiquem embutidos no notebook, podemos usar a linha


In [20]:
%matplotlib inline

ou


In [21]:
%matplotlib notebook

Atenção Como vimos em aula, em algumas instalações a opção notebook não funciona corretamente; aconselho sempre que estiverem usando notebooks, usarem

%matplotlib inline


In [24]:
%matplotlib inline

Agora, podemos usar comandos no estilo MATLAB:


In [25]:
import matplotlib.pyplot as plt
plt.plot([1,2,3,4])
plt.ylabel('meus números')
plt.show()


Observação Os exemplos abaixo foram baseados no tutorial http://matplotlib.org/users/pyplot_tutorial.html

Para desenhar um gráfico, precisamos passar ao matplotlib uma lista de valores para o eixo horizontal, e outra lista de valores (com o mesmo tamanho da primeira) para o eixo vertical; ligando estes pontos, o matplotlib desenha o gráfico. Se passamos apenas uma lista para o matplotlib, ele conclui que esta lista contém os valores a serem colocados no eixo vertical.

Se quisermos escolher valores para o eixo horizontal, fazemos matplotlib.pyplot.plot(x,y):


In [26]:
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
plt.show()


Perceba que, para que o gráfico esteja na janela correta, precisamos usar uma sintaxe um pouco diferente do que usaríamos no MATLAB:


In [27]:
fig = plt.figure()
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])


Out[27]:
[<matplotlib.lines.Line2D at 0x7f0b63de1f60>]

Também podemos selecionar o tipo de traço e a cor, usando exatamente a mesma sintaxe que o MATLAB:


In [28]:
fig = plt.figure()
plt.plot([1,2,3,4], [1,4,9,16], 'ro')
plt.plot([1,2,3,4],[1,4,9,16], 'g', linewidth=2)
plt.plot([1,3,5,7,9], linestyle="dashed", linewidth=4)


Out[28]:
[<matplotlib.lines.Line2D at 0x7f0b63d50240>]

In [31]:
import numpy as np
import matplotlib.pyplot as plt

# t vai de 0 a 5, com subintervalos de 0.2 unidades de comprimento
t = np.arange(0., 5., 0.2)

fig = plt.figure()
# em tracejado vermelho faremos o gráfico de t; 
# em quadrados azuis faremos o gráfico de t**2;
# em triângulos verdes faremos o gráfico de t**3
plt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^')
plt.show()



In [32]:
fig = plt.figure()
plt.plot([1,3,2,7,5,9,4], 'y*', markersize=20)


Out[32]:
[<matplotlib.lines.Line2D at 0x7f0b63bedf98>]

O comando axis permite ajustarmos os limites horizontais e verticais do gráfico:


In [33]:
fig = plt.figure()
plt.plot([1,3,2,7,5,9,4], 'y*', markersize=20)
plt.axis([-1,8,0,10])


Out[33]:
[-1, 8, 0, 10]

Múltiplos gráficos na mesma janela

No pyplot, assim como no MATLAB, temos um conceito de figura e axes (eixos). Todos os comandos de gráfico se aplicam ao eixo atual. A função gca() retorna uma referência ao eixo atual e gcf() retorna a figura atual.

Por exemplo, podemos usar


In [34]:
fig, axes = plt.subplots()
pontos = [1,3,2,7,5,9,4]
axes.plot(pontos, 'y*', markersize=20)
axes.plot(pontos, 'b', linestyle="dotted")
axes.axis([-1,8,0,10])


Out[34]:
[-1, 8, 0, 10]

Agora, vamos criar uma janela com dois subplots:


In [35]:
import numpy as np
import matplotlib.pyplot as plt

def f(t):
    return np.exp(-t) * np.cos(2*np.pi*t)

t1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.02)

plt.figure(1)
plt.subplot(211)
plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')

plt.subplot(212)
plt.plot(t2, np.cos(2*np.pi*t2), 'r--')
plt.show()


O comando subplot() especifica (linha, coluna, figura) em que figura vai de 1 até linhascolunas (As vírgulas são opcionais se linhascolunas<10; então subplot(211) é o mesmo que subplot(2, 1, 1).


In [38]:
import matplotlib.pyplot as plt
plt.figure(1)                # primeira figura
plt.subplot(211)             # primeiro subplot na primeira figura
plt.plot([1, 2, 3])
plt.subplot(212)             # segundo subplot na primeira figura
plt.plot([4, 5, 6])


plt.figure(2)                # segunda figura
plt.plot([4, 5, 6])          # cria um subplot(111) automaticamente

plt.figure(1)                # na figura 1, o subplot(212) ainda é o mais atual
plt.subplot(211)             # selecionar o subplot(211) como atual
plt.title('Easy as 1, 2, 3') # atualizar o título do subplot(211)


Out[38]:
<matplotlib.text.Text at 0x7f0b63d3d9b0>

Adicionando anotações

O comando text() pode ser utilizado para adicionarmos texto em posições arbitrárias, enquanto que xlabel(), ylabel() e title() são utilizados para adicionar texto em posições pré-definidas:


In [41]:
import numpy as np
import matplotlib.pyplot as plt

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

fig = plt.figure(1)
n, bins, patches = plt.hist(x, 50, normed=1, facecolor='g', alpha=0.75)

plt.xlabel('Domínio')
plt.ylabel('Probabilidade')
plt.title('Histograma')
plt.text(60, .025, r'$\mu=100,\ \sigma=15$')
plt.axis([40, 160, 0, 0.03])
plt.grid(True)
plt.show()



In [42]:
import numpy as np
import matplotlib.pyplot as plt

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

fig = plt.figure(1)
n, bins, patches = plt.hist(x, 50, normed=1, facecolor='g', alpha=0.75)

plt.xlabel('Domínio')
plt.ylabel('Probabilidade')
plt.title('Histograma')
plt.text(60, .025, r'$\mu=100,\ \sigma=15$')
plt.axis([40, 160, 0, 0.03])
plt.grid(True)

t = plt.xlabel('Dados', fontsize=14, color='red')

plt.show()


(O r antes da string do título é importante pois significa que o Python não deve tentar interpretar o que se segue)


In [43]:
import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)
line, = ax.plot(t, s, lw=2)

ax.annotate('máximo local', xy=(2, 1), xytext=(3, 1.5),
            arrowprops=dict(facecolor='black', shrink=0.05),
            )

plt.ylim(-2,2)


Out[43]:
(-2, 2)

Podemos selecionar a escala do gráfico usando

plt.xscale(‘log’)

por exemplo.


In [45]:
import numpy as np
import matplotlib.pyplot as plt

# inventar dados no intervalo ]0, 1[
y = np.random.normal(loc=0.5, scale=0.4, size=1000)
y = y[(y > 0) & (y < 1)]
y.sort()
x = np.arange(len(y))

# criar gráficos com diversas escalas
plt.figure()

# linear
plt.subplot(221)
plt.plot(x, y)
plt.yscale('linear')
plt.title('linear')
plt.grid(True)


# log
plt.subplot(222)
plt.plot(x, y)
plt.yscale('log')
plt.title('log')
plt.grid(True)


# log simétrico
plt.subplot(223)
plt.plot(x, y - y.mean())
plt.yscale('symlog', linthreshy=0.05)
plt.title('symlog')
plt.grid(True)

# logit
plt.subplot(224)
plt.plot(x, y)
plt.yscale('logit')
plt.title('logit')
plt.grid(True)


(Fim da Aula 5, ministrada em 27/09/2016)