# Empoderando o Python



# Empoderando o Python

* Importando bibliotecas
* Espaços de nomes
* NumPy
* Matplolib

# Importando bibliotecas


## Sintaxe

`import BIBLIOTECA`

`import BIBLIOTECA as BIB`

`from BIBLIOTECA import FUNCAO1, FUNCAO2, ...`


Após importar os comandos ficam imediatamente disponíveis. É fortemente recomendado que os comandos de importação fiquem no início do arquivo. Quando importando de uma biblioteca utilizando o `import` as funções disponíveis ficam associadas a um espaço de nomes, que é uma forma de evitar conflito de nomes e facilmente identificar a origem do objeto.

## Exemplos de importação


```python
import numpy
```


```python
numpy.sqrt(4)
```




    2.0




```python
import numpy as np
```


```python
np.sqrt(4)
```




    2.0




```python
sqrt(4)
```


```python
from cmath import sqrt, sin, cos
```


```python
sqrt(4)
```




    (2+0j)



# A biblioteca NumPy

* Parte do projeto SciPy;
* Implementa uma estrutura númerica n-dimensional muito poderosa;
* Computacionalmente muito eficiente;
* Possui uma vasta coleção de funções e métodos;
* Funções de álgebra linear (`numpy.linalg`)
* É provavelmente o motivo pelo qual o Python atingiu sua fama.

Inicialmente lançada como `numeric` em 1995, a biblioteca [NumPy](https://www.numpy.org) renomeada em 2005 é provavelmente a responsável pela fama que a linguagem Python possui. É a biblioteca fundamental na computação científica com Python, sendo parte do projeto [SciPy](https://www.scipy.org/). Em sua essência implementa o objeto **numpy.array** que é uma estrutura n-dimensional com suporte a operações vetoriais, matriciais e tensoriais, computacionalmente eficiente em termos de performance e precisão. 

Apesar do Python ser considerada uma lingagem lenta, quando o numpy.array é utilizado de forma correta o speedup obtido é na casa de 3 a 4 ordens de magnitude, muitas vezes ultrapassando a performance de linguagens famosas por computação numérica eficiente como Fortran e Júlia. Isso é possível pois internamente toda computação é realizada de forma extremamente otimizada, quando possível utilizando instruções otimizadas do hardware disponível. Mostraremos exemplos comparando a performance entre uma implementação regular em Python e uma implementada utilizando corretamente o NumPy onde o ganho de performance chega a ser 8000x maior, mas apesar deste exemplo ilustrativo, nosso objetivo com esta aula não é otimização de performance.

A biblioteca NumPy possui uma [vasta coleção de funções](https://docs.scipy.org/doc/numpy/reference/routines.html), aqui trataremos somente de uma parte bem pequena. Dentro da NumPy existem os submódulos: `FFT` (transformada de Fourier), `linalg` (Algebra Linear), `matlib` (operações com matrizes) e `random` (números pseudo aleatórios).

## Operações com Numpy Array

### Criando Numpy Arrays


```python
M = np.array([1, 2, 3, 4, 5])
```


```python
N_lista = [1, 2, 3, 4, 5, 6, 7]
N = np.array(N_lista)
```


```python
I = np.ones(10)
I
```




    array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])




```python
Z = np.zeros_like(I)
Z
```




    array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])




```python
M.dtype
```




    dtype('int64')




```python
I.dtype
```




    dtype('float64')



Como os *numpy arrays*, são otimizados para performance, mudar o seu tamanho não é uma tarefa simples como acontece com as listas Python. Por esta razão esta operação não será explicada durante este curso. Sempre crie os arrays numpy com o tamanho correto para a aplicação.

Os elementos de um array numpy devem pertencer todos ao mesmo tipo de objeto (`int64`, `float64`, `object`, etc), quando adicionado tipos diferentes a um array, ele será convertido para o tipo do array (por exemplo adicionar um número  com casas decimais a um array do tipo `int64` converterá o número para o tipo inteiro. Este tipo de operação deve ser evitada a todo custo. Os tipos de dados válidos para um numpy array podem ser vistos em [https://docs.scipy.org/doc/numpy/reference/arrays.scalars.html]

Caso a biblioteca não consiga identificar o melhor tipo para um array ele irá configurar o tipo `object` que tem o comportamento semelhante as listas python (ou seja todos os tipos podem ser inseridos), mas que possui a pior performance, evite a todo custo.

## Aritmética com Numpy Arrays


```python
u = np.array([2,1,2,0])
v = np.array([1,1,2,3])
```


```python
u + v
```




    array([3, 2, 4, 3])




```python
u - v
```




    array([ 1,  0,  0, -3])




```python
u * v
```




    array([2, 1, 4, 0])




```python
u / v
```




    array([2., 1., 1., 0.])




```python
abs(u-v)
```




    array([1, 0, 0, 3])




```python
u @ v
```




    7



Arrays numpy se comportam na maioria dos casos como vetores matemáticos desta forma as operações ($+$, $-$, $*$, $/$) são aplicadas elemento a elemento. Isso exige que os vetores possuam as mesmas dimensões.

Além disso os arrays numpy também suportam a indexação e o fatiamento similar as listas.

## Exercicio 1

A diferença progressiva de primeira ordem de uma série, é dada pela diferença entre o elemento seguinte da série e o elemento atual. Se consideramos um elementos unitariamente espaçados de uma série, podemos considerar a diferença progressiva como um análogo discreto ao conceito de derivada.

Seja a série $x = \{ x_i \} \; 1 \le i \le \infty$. A $i$-ésima diferença progressiva de primeira ordem é dada por

\begin{equation}
\Delta x_i = x_{i+1} - x_i
\end{equation}

Utilizando o que aprendeu até o momento, crie um algoritmo para calcular a diferença progressiva dos 30 primeiros numeros de Fibonacci armazenados na variável `fibo`


```python
# Armazena os 30 primeiros Fibonacci na lista fibo
n = 30
a, b, i = 0, 1, 2
fibo = [a, b]
while i < n :
    i = i + 1
    a, b = b, a+b
    fibo.append(b)
```


```python
# Sua resposta aqui
```


```python
# Gabarito 1
# %load .resps/difprog.py
```


```python
# Gabarito 2
# %load .resps/difprog_o.py
```

# Gráficos

* Biblioteca `matplotlib`

* Imita o comportamento do Matlab

* Suporte a orientação a objetos

* Suporte a $\LaTeX$

* [Multiplos formatos de gráficos](https://matplotlib.org/gallery/index.html)

* Vamos ver:

  * Função

  * Imagens e Matrizes
  
  * Espalhamento
  
  * Barra
  
  * Setores (Pizza/Torta)
  
  * Histogramas

## Iniciando a MatplotLib


```python
import matplotlib.pyplot as plt
```


```python
x = np.arange(5)
```


```python
plt.plot(x, x**2);
```



## Definindo o domínio

`np.linspace(a, b, n)`

Onde `a` é o limite inferior, `b` o limite superior e `n` o número de intervalos entre os limites.


```python
x = np.linspace(-4, 3, 101)
```


```python
a, b, c = 1, 1, -2
```


```python
y = a*x**2 + b*x + c
```


```python
plt.plot(x, y);
plt.plot(x, .5*x+3);
```



## Exercício

Converta os primeiros 30 números de Fibonacci em um numpy array e crie um gráfico contendo tanto os numeros Fibonacci como as suas diferenças progressivas. Não se esqueça que quando gerando gráficos com mais de uma função é necessário que o número de pontos no domínio seja o mesmo em todas as funções.


```python
# Sua resposta aqui
```


```python
# Gabarito
# %load .resps/fibo_graf.py
```

# Tente

`import antigravity`


```python

```

c2bc47a480cc1238eedd0248a48c54ce2eeaacf7
ipynb
Jupyter Notebook
aulas/03-Numpy_e_Matplotlib.ipynb
igormorgado/introducaopython
26d9eb0a57c22774e43bd3a79de849ca2e9c0f59
MIT
2019-03-18T19:38:19.000Z
2021-01-25T20:36:43.000Z
aulas/03-Numpy_e_Matplotlib.ipynb
igormorgado/introducaopython
26d9eb0a57c22774e43bd3a79de849ca2e9c0f59
MIT
aulas/03-Numpy_e_Matplotlib.ipynb
igormorgado/introducaopython
26d9eb0a57c22774e43bd3a79de849ca2e9c0f59
MIT
2020-03-08T14:23:43.000Z
2020-08-26T14:36:18.000Z
Qwen/Qwen-72B
1. YES
2. YES