Escolar Documentos
Profissional Documentos
Cultura Documentos
PARA
DATA SCIENCE
Apostila do Aluno
Adson Nogueira Alves - Analista Capacitação Técnica
Autor
Bons estudos!
Obs.: todas as imagens desta apostila são de autoria própria.
Sumário
1 Introdução 6
1.1 Visão Geral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2 Ambiente de Desenvolvimento . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3 Material complementar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2 NumPy 8
2.1 NumPy arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.1.1 Funções para criar arrays: arange(), zeros(), ones(), linspace()
e eye() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.1.2 Módulo random . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1.3 Atributos e métodos de arrays . . . . . . . . . . . . . . . . . . . . . . 13
2.2 Exercícios Extras I . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.3 Exercicios Extras I Resolvidos . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.4 Seleção e indexação de numpy arrays . . . . . . . . . . . . . . . . . . . . . . 19
2.4.1 Seleção por chaves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.4.2 Broadcasting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.4.3 Indexação de arrays 2D (matrizes) . . . . . . . . . . . . . . . . . . . . 21
2.4.4 Seleção por expressão lógica . . . . . . . . . . . . . . . . . . . . . . . 23
2.5 Exercícios Extras II . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.6 Exercícios Extras II Resolvidos . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.7 Operações em NumPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.7.1 Universal Array Functions . . . . . . . . . . . . . . . . . . . . . . . . 30
3 Pandas 32
3.1 Séries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.2 Pandas DataFrames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.2.1 Seleção e indexação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.2.2 Lidando com informações faltantes . . . . . . . . . . . . . . . . . . . 46
3.2.3 Agrupamento de dados por groupby . . . . . . . . . . . . . . . . . . . 48
3.2.4 merge, join e concatenate DataFrames . . . . . . . . . . . . . . . . . 51
3.2.5 Operações em DataFrames . . . . . . . . . . . . . . . . . . . . . . . . 58
3.2.6 Entrada e saída de dados . . . . . . . . . . . . . . . . . . . . . . . . . 62
5 Matplotlib 70
5.1 Opções avançadas do Matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . 86
6 Seaborn 106
6.1 Gráficos de distribuições: distplot(), jointplot(), pairplot() e rugplot()106
6.2 Gráficos categóricos: barplot(), countplot(), boxplot(), violinplot(),
stripplot(), swarmplot() e catplot() . . . . . . . . . . . . . . . . . . . . . 115
6.3 Combinando gráficos categóricos . . . . . . . . . . . . . . . . . . . . . . . . . 129
6.4 Gráficos de matrizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
6.4.1 Heatmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
6.5 Grids: PairGrid(), pairplot(), FacetGrid() e JointGrid() . . . . . . . . . 135
6.6 Regressão: lmplot() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
6.7 Formatação, estilos e cores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
6.7.1 Marcadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
6.7.2 Inserindo uma grade . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
6.7.3 Proporção e tamanho . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
10 Conclusão 180
1 Introdução
• Linguagem de programação (LP): uma linguagem artificial usada para controlar o com-
portamento de um sistema ou máquina. Assim como a linguagem humana são definidos
através de regra sintática e semântica, para determinar estrutura e significado, respectiva-
mente.
• Libraries ou Biblioteca: é uma coleção de códigos pré-escritos que são usados para
otimizar a programação.
• API’s: interface que estabelece uma comunicação viavél entre dois sistemas ou plataformas,
agregando funções diversificadas sem precisar saber como elas foram implementadas.
Desta maneira, será abordado em nivel basico ferramentas para preparação, análise e apre-
sentação dos dados, utilizando a linguagem de programação Python e Frameworks/Libraries
como NumPy, Pandas, Matplotlib e Seaborn.
Item Label
1 TensorFlow
2 Keras
3 Scikit-learn
4 Matplotlib
5 Pandas
6 NumPy
7 Pytorch
8 Seaborn
9 Shogun
10 AWS Deep Learning AMI
Outras vantagens como não ser necessário configurar o ambiente, acesso livre a GPUs (Uni-
dades de Processamento Gráfico) e TPU’s (Unidade de processamento de Tensor) responsáveis
por aumentar a velocidade de processamento gráfico e de aprendizagem profunda também são
disponibilizados.
• Programiz [9]
• Udemy [12]
• W3schools [13]
• Medium [6]
• Anaconda [1]
• Kaggle [3]
8
2 NumPy
• O tamanho do ndarray tem um tamanho fixo na criação, alterar o seu tamanho significa
apagar o original e criar um novo ndarray, evitando alocação de memoria desnecessária.
• Para Numpy array é requerido que se tenha o mesmo tipo de dados. Com exceção quando
trabalhamos com arrays de tipo objeto.
• Numpy facilita operações matemáticas além de outros tipos de operações para grande
volume de dados.
• O Python array começa a se tornar ineficiente para tratar o crescente numero de dados
matemáticos e científicos.
Como iremos utilizar a ferramenta Colab não é necessário realizar pré instalação da biblio-
teca, porém caso queira utilizar o NumPy fora desse ambiente será necessário a instalação através
de uma instrução bastante simples no Prompt de Comando (CMD) do seu sistema operacional,
basta utilizar um dos comandos abaixo:
[2]: [1, 2, 3]
[3]: np.array(my_list)
[5]: x = np.array(my_matrix)
print(x)
[[1 2 3]
[4 5 6]
[7 8 9]]
2.1.1 Funções para criar arrays: arange(), zeros(), ones(), linspace() e eye()
Podemos criar arrays específicas através de uma série de funções disponíveis na documentação
[7].
• arange() fornece uma sequência de números entre um valor inicial, um valor final e opci-
onalmente com um passo definido.
[6]: ?np.arange
[7]: np.arange(0,10)
[8]: np.arange(0,11,2)
• zeros() e ones() são funções que criam arrays contendo apenas valores iguais a 0 (zero)
ou 1 (um), respectivamente. Precisamos passar para a função o tamanho do array, ou uma
tupla com a extensão em cada dimensão.
[9]: np.zeros(3)
[10]: np.zeros((5,5))
[11]: np.ones(3)
[12]: np.ones((3,3))
[13]: np.linspace(0,10,3)
[14]: np.linspace(0,10,50)
11
• eye() retorna a matriz identidade, ou seja, a matriz quadrada onde todas as entradas são
zero com exceção dos elementos da diagonal que são iguais a 1.
a = np.eye(dimensão)
[15]: np.eye(4)
Neste módulo da biblioteca é possível gerar números randômicos ou aleatórios. Diversas funções
estão disponíveis:
• rand() fornece array populado com números aleatórios com uma distrbuição uniforme entre
[0, 1[ (incluindo zero e excluindo o 1). A sintaxe é:
onde dim1, dim2, etc são as extensões das dimensões do array retornado.
[16]: np.random.rand(2)
[17]: np.random.rand(5,5)
12
• randn() retorna uma amostra da distribuição normal padrão (gaussiana com média µ = 0
e variância σ = 1). A sintaxe é análoga à do rand():
[18]: np.random.randn(2)
[19]: np.random.randn(7,5)
[20]: np.random.randint(1,100)
[20]: 25
[21]: np.random.randint(1,100,10)
[21]: array([48, 16, 40, 6, 84, 89, 74, 53, 97, 22])
• seed() inicializa o gerador de números aleatórios. Isto é uma boa prática quando traba-
lhamos com números aleatórios, pois torna o resultado determinístico, uma vez que para
um mesmo parâmetro, os mesmos números aleatórios são gerados.
13
np.random.seed(semente)
[22]: np.random.seed(12)
x = np.random.randint(1, 20)
print(x)
x = np.random.randint(1, 20)
print(x)
np.random.seed(12)
x = np.random.randint(1, 20)
print(x)
12
7
12
São funções e atributos intrínsicos dos arrays, considerados dados internos. Usando os arrays a
e b para exemplificar, temos:
[23]: a = np.arange(25)
b = np.random.randint(0,50,10)
[24]: a
[25]: b
[26]: a.reshape(5,5)
14
[27]: b.max()
[27]: 49
[28]: b.argmax()
[28]: 2
[29]: b.min()
[29]: 2
[30]: b.argmin()
[30]: 3
[31]: # Vector
a.shape
[31]: (25,)
[32]: a.reshape(1,25)
[33]: a.reshape(1,25).shape
[34]: a.reshape(25,1)
15
[35]: a.reshape(25,1).shape
[35]: (25, 1)
[36]: b.dtype
[36]: dtype('int32')
[38]: a.dtype
[38]: dtype('float64')
17
[ ]:
[ ]:
[ ]:
18
[48]: array([9138, 7212, 8170, 1588, 9603, 9216, 4279, 2581, 8341, 3785, 5606,
8248, 4802, 4270, 1054])
[49]: 9603
[50]: 4
[51]: 1054
[52]: 14
[53]: x.reshape(3,5)
[3]: arr
Este é o método mais básico de seleção de elementos, sendo exatamente igual ao que vimos
anteriormente. Podemos também selecionar elementos com índices negativos, o que significa
percorrer o array de trás para frente.
[4]: arr[5]
[4]: 5
[5]: arr[2:5]
[6]: arr[-1]
[6]: 10
2.4.2 Broadcasting
arr
20
arr
arr2
[10]: arr2[:] = 99
arr2
Este tipo de alteração impacta também o array original, uma vez que ambos compartilham
o mesmo endereço de memória, exatamente como no caso das listas.
[11]: arr
Para evitar estes problemas, temos que utilizar o método copy() e gerar um novo espaço
de memória.
print(arr_copy)
print(arr)
arr[2:4] = -1
print(arr_copy)
print(arr)
21
[99 99 99 99 99 99 6 7 8 9 10]
[99 99 99 99 99 99 6 7 8 9 10]
[99 99 99 99 99 99 6 7 8 9 10]
[99 99 -1 -1 99 99 6 7 8 9 10]
Para recuperar um único registro, precisamos de dois índices, um para linha e outro para coluna.
Isto pode ser feito de duas maneiras:
x = arr_2d[linha][coluna]
y = arr_2d[linha,coluna]
l = arr_2d[linha]
l = arr_2d[linha,:]
c = arr_2d[:,coluna]
arr_2d
arr_2d[1][0]
[15]: 20
[16]: arr_2d[1,0]
[16]: 20
22
s = arr_2d[linha_inicio:linha_fim, coluna_inicio:coluna_fim]
print(arr_2d[:2,1:])
[[ 5 10 15]
[20 25 30]
[35 40 45]]
[[10 15]
[25 30]]
[18]: #linha 2
arr_2d[2]
[19]: #linha 2
arr_2d[2,:]
arr2d
[20]: array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[2., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
[3., 3., 3., 3., 3., 3., 3., 3., 3., 3.],
[4., 4., 4., 4., 4., 4., 4., 4., 4., 4.],
23
[5., 5., 5., 5., 5., 5., 5., 5., 5., 5.],
[6., 6., 6., 6., 6., 6., 6., 6., 6., 6.],
[7., 7., 7., 7., 7., 7., 7., 7., 7., 7.],
[8., 8., 8., 8., 8., 8., 8., 8., 8., 8.],
[9., 9., 9., 9., 9., 9., 9., 9., 9., 9.]])
[21]: array([[2., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
[4., 4., 4., 4., 4., 4., 4., 4., 4., 4.],
[6., 6., 6., 6., 6., 6., 6., 6., 6., 6.],
[8., 8., 8., 8., 8., 8., 8., 8., 8., 8.]])
[22]: array([[6., 6., 6., 6., 6., 6., 6., 6., 6., 6.],
[4., 4., 4., 4., 4., 4., 4., 4., 4., 4.],
[2., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
[7., 7., 7., 7., 7., 7., 7., 7., 7., 7.]])
Podemos obter um array de valores booleanos ao utilizar uma expressão lógica envolvendo o array.
Com isto, podemos selecionar apenas os elementos do array original que satisfazem uma certa
condição:
[25]: bool_arr
[25]: array([False, False, False, False, True, True, True, True, True,
True])
24
[26]: arr[bool_arr]
[28]: x = 2
arr[arr > x]
arr = np.arange(0,50)
[ ]:
[ ]:
26
arr = np.arange(0,50)
[48]: arr[arr%2 == 1]
[48]: array([ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33,
35, 37, 39, 41, 43, 45, 47, 49])
[50]: arr[arr%2 == 1] = -1
arr
[50]: array([ 0, -1, 2, -1, 4, -1, 6, -1, 8, -1, 10, -1, 12, -1, 14, -1, 16,
-1, 18, -1, 20, -1, 22, -1, 24, -1, 26, -1, 28, -1, 30, -1, 32, -1,
34, -1, 36, -1, 38, -1, 40, -1, 42, -1, 44, -1, 46, -1, 48, -1])
27
[0 1 2 3 4 5 6 7 8 9]
[5]: # A divisão por zero gera apenas um aviso de runtime e seu resultado é um␣
,→nan
arr/arr
C:\Users\jagapadi\AppData\Local\Continuum\anaconda3\envs\jupyter\lib\site-
packages\ipykernel_launcher.py:2: RuntimeWarning: invalid value encountered␣
,→in
true_divide
[5]: array([nan, 1., 1., 1., 1., 1., 1., 1., 1., 1.])
[6]: # outra divisão por zero, que desta vez retorna o valor de infinito
1/arr
C:\Users\jagapadi\AppData\Local\Continuum\anaconda3\envs\jupyter\lib\site-
packages\ipykernel_launcher.py:2: RuntimeWarning: divide by zero␣
,→encountered in
28
true_divide
[7]: arr**2
[8]: arr.sum()
[8]: 45
[9]: x = np.arange(0,25).reshape(5,5)
print(x)
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]]
[10]: arr.cumsum()
29
[11]: print(x.cumsum())
média = 12.0
As Universal Array Functions ou ufuncs são funções especiais que agem em todos os elementos
de um array.
[16]: 9
C:\Users\jagapadi\AppData\Local\Continuum\anaconda3\envs\jupyter\lib\site-
packages\ipykernel_launcher.py:1: RuntimeWarning: divide by zero␣
,→encountered in
log
"""Entry point for launching an IPython kernel.
3 Pandas
3.1 Séries
Uma série é muito semelhante a uma matriz NumPy (Pandas series foi construída sobre
o objeto da matriz NumPy). O que diferencia a matriz NumPy de uma série é que esta pode
ser indexada por um rótulo, em vez de apenas um índice inteiro. Além disso, a série não precisa
necessariamente conter dados numéricos, mas sim qualquer objeto Python arbitrário.
Para criar uma série, pode-se converter uma lista, numpy array, ou dicionário em pandas
em séries:
[3]: pd.Series(data=my_list)
[3]: 0 10
1 20
2 30
dtype: int64
[4]: a 10
b 20
c 30
dtype: int64
[5]: a 10
b 20
c 30
dtype: int64
[6]: pd.Series(arr)
[6]: 0 1.1
1 1.2
2 1.3
dtype: float64
[7]: a 1.1
b 1.2
c 1.3
dtype: float64
** Dictionary**
[8]: pd.Series(dic)
[8]: x 10
y 20
z 30
dtype: int64
[9]: pd.Series(data=labels)
[9]: 0 a
1 b
2 c
dtype: object
Podemos passar explicitamente para o construtor da série quem serão os índices, que
podemo ser utilizados para indexação.
[12]: ser1
[12]: USA 1
Germany 2
Brazil 3
Japan 4
dtype: int64
[14]: ser2
[14]: USA 1
Germany 2
Italy 5
Japan 4
dtype: int64
[15]: ser1['USA']
[15]: 1
Japan 8.0
USA 2.0
dtype: float64
Podemos concatenar séries com a função concat(), passando as séries a serem concate-
nadas em uma lista e a direção que a concatenação deve ser realizada.
[17]: 0 1
USA 1.0 1.0
Germany 2.0 2.0
Brazil 3.0 NaN
Japan 4.0 4.0
Italy NaN 5.0
[18]: USA 1
Germany 2
Brazil 3
Japan 4
USA 1
Germany 2
Italy 5
Japan 4
dtype: int64
[4]: df
[4]: W X Y Z
A 2.706850 0.628133 0.907969 0.503826
B 0.651118 -0.319318 -0.848077 0.605965
C -2.018168 0.740122 0.528813 -0.589001
D 0.188695 -0.758872 -0.933237 0.955057
E 0.190794 1.978757 2.605967 0.683509
[5]: df['X']
[5]: A 0.628133
B -0.319318
C 0.740122
D -0.758872
E 1.978757
Name: X, dtype: float64
[6]: df[['W','Z']]
[6]: W Z
A 2.706850 0.503826
B 0.651118 0.605965
C -2.018168 -0.589001
D 0.188695 0.955057
37
E 0.190794 0.683509
[7]: A 2.706850
B 0.651118
C -2.018168
D 0.188695
E 0.190794
Name: W, dtype: float64
[8]: type(df['W'])
[8]: pandas.core.series.Series
Para criar uma nova coluna utilizamos a mesma notação dos dicionários, porém ao invés
de utilizar uma chave utilizamos o rótulo de uma coluna. Também devemos tomar cuidado pois
o elemento a ser inserido deve ser uma série.
[10]: df
[10]: W X Y Z new
A 2.706850 0.628133 0.907969 0.503826 3.614819
B 0.651118 -0.319318 -0.848077 0.605965 -0.196959
C -2.018168 0.740122 0.528813 -0.589001 -1.489355
D 0.188695 -0.758872 -0.933237 0.955057 -0.744542
E 0.190794 1.978757 2.605967 0.683509 2.796762
[11]: W X Y Z
A 2.706850 0.628133 0.907969 0.503826
B 0.651118 -0.319318 -0.848077 0.605965
38
Note que o DataFrame original não é alterado desta maneira! A função drop() retorna
um novo DataFrame que é uma cópia do original, porém sem os dados removidos.
[12]: df
[12]: W X Y Z new
A 2.706850 0.628133 0.907969 0.503826 3.614819
B 0.651118 -0.319318 -0.848077 0.605965 -0.196959
C -2.018168 0.740122 0.528813 -0.589001 -1.489355
D 0.188695 -0.758872 -0.933237 0.955057 -0.744542
E 0.190794 1.978757 2.605967 0.683509 2.796762
[14]: df
[14]: W X Y Z
A 2.706850 0.628133 0.907969 0.503826
B 0.651118 -0.319318 -0.848077 0.605965
C -2.018168 0.740122 0.528813 -0.589001
D 0.188695 -0.758872 -0.933237 0.955057
E 0.190794 1.978757 2.605967 0.683509
E podemos remover linhas com a mesma função, apenas alterando o valor do parâmetro
axis:
[15]: W X Y Z
A 2.706850 0.628133 0.907969 0.503826
B 0.651118 -0.319318 -0.848077 0.605965
C -2.018168 0.740122 0.528813 -0.589001
D 0.188695 -0.758872 -0.933237 0.955057
39
[16]: df.loc['A']
[16]: W 2.706850
X 0.628133
Y 0.907969
Z 0.503826
Name: A, dtype: float64
[17]: W X Y Z
A 2.706850 0.628133 0.907969 0.503826
D 0.188695 -0.758872 -0.933237 0.955057
[18]: df.iloc[2]
[18]: W -2.018168
X 0.740122
Y 0.528813
Z -0.589001
Name: C, dtype: float64
[19]: df.iloc[[1,3]]
[19]: W X Y Z
B 0.651118 -0.319318 -0.848077 0.605965
D 0.188695 -0.758872 -0.933237 0.955057
[20]: df.loc['B','Y']
[20]: -0.8480769834036315
[21]: df.loc[['A','B'],['W','Y']]
40
[21]: W Y
A 2.706850 0.907969
B 0.651118 -0.848077
Podemos também realizar uma seleção condicional, de maneira idêntica a que fizemos com
os numpy arrays:
[22]: df
[22]: W X Y Z
A 2.706850 0.628133 0.907969 0.503826
B 0.651118 -0.319318 -0.848077 0.605965
C -2.018168 0.740122 0.528813 -0.589001
D 0.188695 -0.758872 -0.933237 0.955057
E 0.190794 1.978757 2.605967 0.683509
[23]: df > 0
[23]: W X Y Z
A True True True True
B True False False True
C False True True False
D True False False True
E True True True True
[24]: W X Y Z
A 2.706850 0.628133 0.907969 0.503826
B 0.651118 NaN NaN 0.605965
C NaN 0.740122 0.528813 NaN
D 0.188695 NaN NaN 0.955057
E 0.190794 1.978757 2.605967 0.683509
[25]: W X Y Z
A 2.706850 0.628133 0.907969 0.503826
B 0.651118 -0.319318 -0.848077 0.605965
41
[26]: A 0.907969
B -0.848077
D -0.933237
E 2.605967
Name: Y, dtype: float64
[27]: Y X
A 0.907969 0.628133
B -0.848077 -0.319318
D -0.933237 -0.758872
E 2.605967 1.978757
[28]: W X Y Z
A 2.706850 0.628133 0.907969 0.503826
E 0.190794 1.978757 2.605967 0.683509
Algumas opções mais sofisticadas para a indexação estão disponíveis no pandas. Por
exemplo, podemos resetar ou alterar os índices, e até mesmo criar hierarquias de índices.
[29]: df
[29]: W X Y Z
A 2.706850 0.628133 0.907969 0.503826
B 0.651118 -0.319318 -0.848077 0.605965
C -2.018168 0.740122 0.528813 -0.589001
D 0.188695 -0.758872 -0.933237 0.955057
E 0.190794 1.978757 2.605967 0.683509
42
[30]: index W X Y Z
0 A 2.706850 0.628133 0.907969 0.503826
1 B 0.651118 -0.319318 -0.848077 0.605965
2 C -2.018168 0.740122 0.528813 -0.589001
3 D 0.188695 -0.758872 -0.933237 0.955057
4 E 0.190794 1.978757 2.605967 0.683509
Podemos criar uma nova série em uma coluna e utilizar a mesma como índices:
[33]: df
[33]: W X Y Z States
A 2.706850 0.628133 0.907969 0.503826 CA
B 0.651118 -0.319318 -0.848077 0.605965 NY
C -2.018168 0.740122 0.528813 -0.589001 WY
D 0.188695 -0.758872 -0.933237 0.955057 OR
E 0.190794 1.978757 2.605967 0.683509 CO
[34]: df.set_index('States')
[34]: W X Y Z
States
CA 2.706850 0.628133 0.907969 0.503826
NY 0.651118 -0.319318 -0.848077 0.605965
WY -2.018168 0.740122 0.528813 -0.589001
OR 0.188695 -0.758872 -0.933237 0.955057
CO 0.190794 1.978757 2.605967 0.683509
[35]: df
[35]: W X Y Z States
A 2.706850 0.628133 0.907969 0.503826 CA
43
[36]: df.set_index('States',inplace=True)
[37]: df
[37]: W X Y Z
States
CA 2.706850 0.628133 0.907969 0.503826
NY 0.651118 -0.319318 -0.848077 0.605965
WY -2.018168 0.740122 0.528813 -0.589001
OR 0.188695 -0.758872 -0.933237 0.955057
CO 0.190794 1.978757 2.605967 0.683509
Pandas permite o uso de múltiplos índices e até mesmo criar uma hierarquia de índices.
Por exemplo, podemos criar uma lista de tuplas e utilizar a função MultiIndex.from_tuples()
para criar esta estrutura.
[('G1', 1), ('G1', 2), ('G1', 3), ('G2', 1), ('G2', 2), ('G2', 3)]
[41]: hier_index
('G2', 3)],
)
df
[42]: A B
G1 1 0.302665 1.693723
2 -1.706086 -1.159119
3 -0.134841 0.390528
G2 1 0.166905 0.184502
2 0.807706 0.072960
3 0.638787 0.329646
Neste caso, a indexação de linhas por meio do loc[] pode retornar um DataFrame, ao
invés de uma série:
[43]: df.loc['G1']
[43]: A B
1 0.302665 1.693723
2 -1.706086 -1.159119
3 -0.134841 0.390528
Para obter apenas uma linha, precisamos utilizar a indexação do DataFrame obtido na
primeira indexação:
[44]: df.loc['G1'].loc[1]
[44]: A 0.302665
B 1.693723
Name: 1, dtype: float64
Os nomes dos índices podem ser lidos e laterados por meio da propriedade: index.names
[45]: df.index.names
[47]: df
[47]: A B
Group Num
G1 1 0.302665 1.693723
2 -1.706086 -1.159119
3 -0.134841 0.390528
G2 1 0.166905 0.184502
2 0.807706 0.072960
3 0.638787 0.329646
A indexação nesta estrutura hierárquica pode ser feita por meio do método gs() também,
o qual permite escolher o nível da hierarquia por meio do parâmetro level:
[48]: df.xs('G1')
[48]: A B
Num
1 0.302665 1.693723
2 -1.706086 -1.159119
3 -0.134841 0.390528
[49]: df.xs(['G1',1])
[49]: A 0.302665
B 1.693723
Name: (G1, 1), dtype: float64
[50]: df.xs(1,level='Num')
[50]: A B
Group
G1 0.302665 1.693723
G2 0.166905 0.184502
46
No pandas, informações faltantes são exibidas como NaN (not a number ). Internamente, elas são
do tipo np.nan.
[3]: df
[3]: A B C
0 1.0 5.0 1
1 2.0 NaN 2
2 NaN NaN 3
[4]: df.isnull()
[4]: A B C
0 False False False
1 False True False
2 True True False
dropna() e fillna() E podemos remover todas as linhas que contém ao menos um registro
faltante com o dropna(). Para realizar a mesma operação com colunas, basta passar o parâ-
metro axis=1. Alternativamente, você pode definir um limite de valores faltantes tolerável, ou
threshold, passando o parâmetro thresh.
[5]: df.dropna()
[5]: A B C
0 1.0 5.0 1
[6]: df.dropna(axis=1)
47
[6]: C
0 1
1 2
2 3
[7]: df.dropna(thresh=2)
[7]: A B C
0 1.0 5.0 1
1 2.0 NaN 2
Uma saída também muito utilizada quando em face de dados faltantes é simplesmente
substitui-los por algum valor padrão. Isso pode ser feito por meio do método fillna(). O que
muitas pessoas fazem é utilizar valores médios ou medianas das séries, de modo a impactar de
maneira mínima as estatísticas das mesmas.
[8]: df.fillna(value='algo')
[8]: A B C
0 1 5 1
1 2 algo 2
2 algo algo 3
[9]: df['A'].fillna(value=df['A'].mean())
[9]: 0 1.0
1 2.0
2 1.5
Name: A, dtype: float64
for i in col:
df1[i].fillna(value=df1[i].mean(), inplace=True)
df1
[11]: A B C
0 1.0 5.0 1
1 2.0 5.0 2
2 1.5 5.0 3
O método groupby do pandas DataFrame permite que você agrupe dados para aplicar funções
especiais, chamadas de funções agregativas nos mesmos. Isto é muito utilizado quando precisamos
obter as estatísticas de grupos selecionados dentro dos dados de um DataFrame, por exemplo.
data
[2]: df = pd.DataFrame(data)
[3]: df
O objeto retornado pelo groupby não tem muita utilidade nesta forma, porém podemos
aplicar uma série de funções nele e extrair por exemplo, as estatísticas.
[5]: by_comp.mean()
[5]: Sales
Company
FB 296.5
GOOG 160.0
MSFT 232.0
[6]: by_comp.std()
[6]: Sales
Company
FB 75.660426
GOOG 56.568542
MSFT 152.735065
[7]: by_comp.min()
[8]: by_comp.max()
50
[9]: by_comp.count()
Um resumo das estatísticas pode ser obtido por meio do método describe()
[10]: by_comp.describe()
[10]: Sales
count mean std min 25% 50% 75% max
Company
FB 2.0 296.5 75.660426 243.0 269.75 296.5 323.25 350.0
GOOG 2.0 160.0 56.568542 120.0 140.00 160.0 180.00 200.0
MSFT 2.0 232.0 152.735065 124.0 178.00 232.0 286.00 340.0
[11]: by_comp.describe().transpose()
[12]: by_comp.describe().transpose()['GOOG']
51
[5]: df1
[5]: A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 C3 D3
[6]: df2
[6]: A B C D
4 A4 B4 C4 D4
5 A5 B5 C5 D5
6 A6 B6 C6 D6
7 A7 B7 C7 D7
[7]: df3
[7]: A B C D
8 A8 B8 C8 D8
9 A9 B9 C9 D9
10 A10 B10 C10 D10
11 A11 B11 C11 D11
A concatenação dos DataFrames é realizada pela função concat(), onde devemos passar
como parâmetro uma lista contendo os DataFrames a serem concatenados. O padrão desta
função é seguir a ordem dos índices, colocando nas mesmas colunas os dados com os mesmos
rótulos. Porém, podemos subverter esta ordem fornecendo o parâmetro axis=1.
[8]: A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 C3 D3
4 A4 B4 C4 D4
5 A5 B5 C5 D5
53
6 A6 B6 C6 D6
7 A7 B7 C7 D7
8 A8 B8 C8 D8
9 A9 B9 C9 D9
10 A10 B10 C10 D10
11 A11 B11 C11 D11
[9]: A B C D A B C D A B C D
0 A0 B0 C0 D0 NaN NaN NaN NaN NaN NaN NaN NaN
1 A1 B1 C1 D1 NaN NaN NaN NaN NaN NaN NaN NaN
2 A2 B2 C2 D2 NaN NaN NaN NaN NaN NaN NaN NaN
3 A3 B3 C3 D3 NaN NaN NaN NaN NaN NaN NaN NaN
4 NaN NaN NaN NaN A4 B4 C4 D4 NaN NaN NaN NaN
5 NaN NaN NaN NaN A5 B5 C5 D5 NaN NaN NaN NaN
6 NaN NaN NaN NaN A6 B6 C6 D6 NaN NaN NaN NaN
7 NaN NaN NaN NaN A7 B7 C7 D7 NaN NaN NaN NaN
8 NaN NaN NaN NaN NaN NaN NaN NaN A8 B8 C8 D8
9 NaN NaN NaN NaN NaN NaN NaN NaN A9 B9 C9 D9
10 NaN NaN NaN NaN NaN NaN NaN NaN A10 B10 C10 D10
11 NaN NaN NaN NaN NaN NaN NaN NaN A11 B11 C11 D11
Tipos de merge: podemos aglutinar os dados também por meio da função merge, que opera em
pares de DataFrames e seleciona quais dados manter de acordo com o tipo de merge: left, right,
outer ou inner. Estas opções são exatamente iguais às opções que existem em bancos de dados
relacionais do tipo Sql, correspondendo à preservação dos registros com chaves no DataFrame
da esquerda (left), da direita (right), que aparecem em ambos os DataFrames obrigatioriamente
(inner, ou na intersecção das keys) ou que aparecem em um ou outro dataframe (outter, ou na
união das keys).
[11]: left
[11]: key A B
0 K1 A0 B0
1 K4 A1 B1
2 K2 A2 B2
3 K3 A3 B3
[12]: right
[12]: key C D
0 K0 C0 D0
1 K1 C1 D1
2 K2 C2 D2
3 K3 C3 D3
[13]: key A B C D
0 K1 A0 B0 C1 D1
1 K4 A1 B1 NaN NaN
2 K2 A2 B2 C2 D2
3 K3 A3 B3 C3 D3
[14]: key A B C D
0 K1 A0 B0 C1 D1
1 K2 A2 B2 C2 D2
2 K3 A3 B3 C3 D3
3 K0 NaN NaN C0 D0
[15]: key A B C D
0 K1 A0 B0 C1 D1
1 K2 A2 B2 C2 D2
2 K3 A3 B3 C3 D3
[16]: key A B C D
0 K1 A0 B0 C1 D1
1 K4 A1 B1 NaN NaN
2 K2 A2 B2 C2 D2
3 K3 A3 B3 C3 D3
4 K0 NaN NaN C0 D0
[17]: key A B C D
0 K1 A0 B0 C1 D1
1 K2 A2 B2 C2 D2
2 K3 A3 B3 C3 D3
Note que o padrão do merge é por inner join, que é a opção mais segura: selecionar as
chaves que estão presentes em ambos os DataFrames. A seguir, um exemplo mais elaborado,
com mais chaves
[19]: left
56
[20]: right
[26]: A B C D
K0 A0 B0 C0 D0
K1 A1 B1 NaN NaN
K2 A2 B2 C2 D2
Por fim, o método join é conveniente para combinar as colunas de dois DataFrames cujos
índices podem ser diferentes.
[28]: left
58
[28]: A B
K0 A0 B0
K1 A1 B1
K2 A2 B2
[29]: right
[29]: C D
K0 C0 D0
K2 C2 D2
K3 C3 D3
[30]: left.join(right)
[30]: A B C D
K0 A0 B0 C0 D0
K1 A1 B1 NaN NaN
K2 A2 B2 C2 D2
[31]: A B C D
K0 A0 B0 C0 D0
K1 A1 B1 NaN NaN
K2 A2 B2 C2 D2
K3 NaN NaN C3 D3
Pode-se realizar uma série de operações sobre as Series e DataFrames, sendo que muitas destas
são geralmente de natureza estatística.
unique(), nunique(), value_counts(), sum(), mean() e std() Valores únicos e não únicos,
assim como contagem de valores absolutos podem ser obtidos a partir dos métodos unique(),
nunique() e value_counts(), respectivamente. Para séries com valores numéricos, pode-se
obter somas e estatísticas com sum(), mean() e std() por exemplo.
[2]: df['col2'].unique()
[3]: df['col2'].nunique()
[3]: 3
[4]: df['col2'].value_counts()
[4]: 444 2
555 1
666 1
Name: col2, dtype: int64
[5]: df['col1'].sum()
[5]: 10
[6]: df['col1'].mean()
[6]: 2.5
[7]: df['col1'].std()
[7]: 1.2909944487358056
[9]: newdf
apply() Existem também a opção de aplicar uma função em todos os dados de um DataFrame
por meio do método apply().
[11]: df['col1'].apply(vezes2)
[11]: 0 2
1 4
2 6
3 8
Name: col1, dtype: int64
[12]: df['col3'].apply(len)
[12]: 0 3
1 3
2 3
3 3
Name: col3, dtype: int64
Remover uma coluna inteira é simples, basta utilizar a palavra reservada del e a série da
coluna:
[14]: df
2 666 ghi
3 444 xyz
Os nomes das colunas e rótulos dos índices podem ser obtidos das propriedades columns
e index:
[15]: df.columns
[16]: df.index
Ordenamento dos dados podem ser obtido de maneir direta, por meio do método
sort_values(). O parâmetro do mesmo é a coluna, ou série que deverá ser utilizada para
as comparações durante o ordenamento.
[17]: df
Por fim, podemos também criar uma tabela de pivôs a partir de um DataFrame. Esta
tabela simplesmente agrega os valores em uma ordem definida por índices e colunas, conforme o
exemplo a seguir:
62
df = pd.DataFrame(data)
[20]: df
[20]: A B C D
0 foo one x 1
1 foo one y 3
2 foo two x 2
3 bar two y 5
4 bar one x 4
5 bar one y 1
[21]: C x y
A B
bar one 4.0 1.0
two NaN 5.0
foo one 1.0 3.0
two 2.0 NaN
Nos exemplos que vimos até o momento, tivemos que digitar os valores que seriam armazenados
nas séries ou DataFrames. Obviamente esta não é uma situação real de trabalho, onde muitas
vezes os dados são fornecidos por outras ferramentas, tais como gerenciadores de planilhas do
tipo Excel ou OpenOffice, arquivos de dados, páginas da internet ou bancos de dados relacionais.
Vamos ver como ler e escrever os dados tanto em planilhas quanto em arquivos do tipo csv
(comma separated values - valores separados por vírgula).
[2]: df = pd.read_csv('exemplo.csv')
df
[2]: a b c d
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
3 12 13 14 15
De maneira análoga, os dados podem ser escritos no mesmo formato por meio do método
to_csv()
A leitura é feita pela função read_excel(). Você pode inclusive escolher até mesmo qual
aba gostaria de ler, passando o parâmetro sheet_name.
[4]: Unnamed: 0 a b c d
0 0 0 1 2 3
1 1 4 5 6 7
2 2 8 9 10 11
3 3 12 13 14 15
A escrita para o formato Excel é feita pelo método to_excel(), onde da mesma maneira
a aba da planilha de destino pode ser escolhida. Para realizar esta operação, é necessária a
instalação do módulo openpyxl. Isto pode ser realizado no terminal por meio do comando
[5]: df.to_excel('Excel_Sample.xlsx',sheet_name='Sheet1')
Para ler de uma página html, você precisa ter instaladas as bibliotecas htmllib5, lxml e
BeautifulSoup4. Para isto, basta digitar no terminal os seguintes comandos:
E em seguida reiniciar seu jupyter notebook. Feito isto, Pandas pode ler informações de
tabelas no formato html. Por exemplo, a leitura dos dados de um site do governo americano onde
constam informações sobre bancos falidos pode ser obtida por meio da função read_html().
[6]: df = pd.read_html('http://www.fdic.gov/bank/individual/failed/banklist.
,→html')
[7]: df[0].head()
[1]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
10. Use o numpy para gerar 25 números aleatório de distribuição normal padrão (gaussiana
com média µ = 0 e desvio padrão σ = 1).
66
[ ]:
array([[0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1 ],
[0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2 ],
[0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3 ],
[0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4 ],
[0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5 ],
[0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6 ],
[0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.7 ],
[0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.8 ],
[0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.9 ],
[0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1. ]])
[ ]:
[ ]:
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25]])
array([[ 2],
[ 7],
[12]])
•
67
[ ]:
[ ]:
[ ]:
[ ]:
68
Nos exercícios abaixo iremos utilizar os dados de salários da cidade de São Francisco, SF
Salaries Dataset [3] do site do Kaggle [8].
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
69
11. Qual e média da base salárial (BasePay) de todos os funcionários no período de 2011-2014?
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
70
5 Matplotlib
O Matplotlib é a biblioteca de visualização de dados com Python. Foi criado por John
Hunter, com o intuito de replicar os recursos do MatLab no Python, sua documentação esta
disponível em [5]. Caso queira utilizar fora do Collab é necessário realizar a instalação através da
instrução:
%matplotlib inline
[3]: x
[4]: y
O comando básico é a função plot(), que gera um gráfico a partir dos dados que são
passados como parâmetros. Outras funções fazem ajustes das informações exibidas na tela, tal
como os títulos dos dados nos eixos e o título do gráfico em si, por exemplo.
71
Podemos criar múltiplos gráficos na mesma área de pintura com a função subplot():
[7]: # criar uma figura, que nada mais é do que uma tela de pintura vazia
fig = plt.figure()
# Figura principal
axes1.plot(x, y, 'b')
axes1.set_xlabel('eixo X axes1')
axes1.set_ylabel('eixo Y axes1')
axes1.set_title('Título axes1')
# Figura do inset
axes2.plot(y, x, 'r')
axes2.set_xlabel('eixo X axes2')
axes2.set_ylabel('eixo Y axes2')
axes2.set_title('Título axes2');
74
[9]: # similar ao plt.figure() mas retorna uma tupla com a figura e os eixos
fig, axes = plt.subplots()
Você pode especificar o número de colunas e linhas quando cria o objeto axes:
[11]: # o objeto axes é um array de objetos que podem ser utilizados para␣
,→plotar gráficos
axes
dtype=object)
# mostar a figura
fig
[12]:
for ax in axes:
ax.plot(x, y, 'g')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('title')
plt.tight_layout()
axes.plot(x, y, 'r')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('título');
[16]: fig.savefig("figura.png")
[18]: ax.set_title("Título")
ax.set_xlabel("eixo x")
ax.set_ylabel("eixo y")
A função legend() usa um argumento opcional de keyword loc que pode ser
usado para especificar onde na figura a legenda deve ser fixada. Os valores
80
As cores e estilos dos traços também podem ser determinados por meio de
parâmetros. Uma maneira muito usual é utilizar a notação do tipo MATLAB.
Também podemos definir cores por seus nomes ou códigos hexadecimais RGB
e, opcionalmente, fornecer um valor de transparência, ou alfa, por meio dos
argumentos color ealpha.
# traços customizados
line, = ax.plot(x, x+8, color="black", lw=1.50)
line.set_dashes([5, 10, 15, 10]) # formato: comprimento da linha,␣
,→comprimento do espaço, ...
83
# símbolos de marcadores: marker = '+', 'o', '*', 's', ',', '.', '1',␣
,→'2', '3', '4', ...
axes[0].plot(x, x ** 2, x, x ** 3)
84
axes[1].plot(x, x ** 2, x, x ** 3)
axes[1].axis('tight')
axes[1].set_title("eixos do tipo 'tight axes'")
axes[2].plot(x, x ** 2, x, x ** 3)
axes[2].set_ylim([0, 60])
axes[2].set_xlim([2, 5])
axes[2].set_title("intervalos customizados");
[25]: plt.scatter(x,y)
plt.show()
85
%matplotlib inline
axes[0].plot(x, x ** 2, x, np.exp(x))
87
axes[0].set_title("Escala linear")
ax.set_xticks([1, 2, 3, 4, 5])
ax.set_xticklabels([r'$\alpha$',
r'$\beta$',
r'$\gamma$',
r'$\delta$',
r'$\epsilon$'],
fontsize=18) # notação no formato LaTeX
88
Em muitas situações podemos ter uma variação muito grande dos valores
em um eixo, até mesmo em ordens de grandeza. Neste caso, é aconselhável
utilizar notação científica.
fig, ax = plt.subplots(1, 1)
ax.plot(x, x ** 2, x, np.exp(x))
ax.set_yticks([0, 50, 100, 150])
ax.set_title("espaçamento de eixos")
ax.set_xlabel("x")
ax.set_ylabel("y");
90
ax.set_title("Título")
ax.set_xlabel("x")
ax.set_ylabel("y")
# aparência padrão
axes[0].plot(x, x**2, x, x**3, lw=2)
axes[0].grid(True)
# aparência customizada
axes[1].plot(x, x**2, x, x**3, lw=2)
axes[1].grid(color='b', alpha=0.5, linestyle='dashed', linewidth=0.5)
92
ax.spines['bottom'].set_color('blue')
ax.spines['top'].set_color('blue')
ax.spines['left'].set_color('red')
ax.spines['left'].set_linewidth(2)
ax2 = ax1.twinx()
ax2.plot(x, x**3, lw=2, color="red")
ax2.set_ylabel(r"volume $(m^3)$", fontsize=18, color="red")
for label in ax2.get_yticklabels():
label.set_color("red")
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data', 0)) # posição do eixo x em y=0
94
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data', 0)) # posição do eixo y em x=0
[13]: n = np.array([0,1,2,3,4,5])
axes[0].scatter(xx, xx + 0.25*np.random.randn(len(xx)))
axes[0].set_title("dispersão")
for g in gs:
ax = fig.add_subplot(g)
fig.tight_layout()
98
# inset
inset_ax = fig.add_axes([0.3, 0.55, 0.35, 0.35]) # X, Y, largura, altura
# intervalo do eixo
inset_ax.set_xlim(-.2, .2)
inset_ax.set_ylim(-.005, .01)
inset_ax.set_xticks([-0.1,0,.1]);
[ ]: fig, ax = plt.subplots()
cb = fig.colorbar(p, ax=ax)
[ ]: fig, ax = plt.subplots()
im.set_interpolation('bilinear')
cb = fig.colorbar(im, ax=ax)
101
[ ]: fig, ax = plt.subplots()
[ ]: fig = plt.figure(figsize=(14,6))
cb = fig.colorbar(p, shrink=0.5)
[ ]: fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(1, 1, 1, projection='3d')
Por fim, podemos fazer projeções do tipo curvas de nível nos planos que
delimitam os gráficos, facilitando sua interpretação.
[ ]: fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(1,1,1, projection='3d')
ax.set_xlim3d(-np.pi, 2*np.pi);
ax.set_ylim3d(0, 3*np.pi);
ax.set_zlim3d(-np.pi, 2*np.pi);
105
6 Seaborn
O repositório tips por exemplo mostra dados de gorjetas que atendentes de restaurantes
receberam.
[3]: tips.head()
[4]: sns.distplot(tips[('total_bill')])
A função jointplot() permite basicamente que você combine duas representações dis-
tintas, por meio do parâmetro kind para comparar com scatter, reg, resid, kde e hex.
Como o próprio nome sugere, pairplot() exibe as relações entre pares de variáveis em um
pandas DataFrame para as colunas numéricas e também exibe uma escala de cores para colunas
com variáveis categóricas.
[9]: sns.pairplot(tips)
[10]: sns.pairplot(tips,hue='sex',palette='coolwarm')
rugplot() é um conceito muito simples, ele apenas traça uma marca para cada ponto de
uma distribuição, formando algo parecido com um tapete (daí o nome).
[11]: sns.rugplot(tips['total_bill'])
[12]: sns.kdeplot(tips[('total_bill')])
sns.rugplot(tips[('total_bill')])
[13]: sns.kdeplot(tips[('tip')])
sns.rugplot(tips[('tip')])
• factorplot
• boxplot
• violinplot
• stripplot
• swarmplot
• barplot
• countplot
[3]: tips.describe()
barplot() e countplot() são muito semelhantes, pois ambos permitem que você ob-
tenha dados agregados de um recurso categórico em seus dados. O primeiro é um gráfico que
permite agregar os dados categóricos com base em alguma função (por padrão a média).
[4]: sns.barplot(x='sex',y='total_bill',data=tips)
Você pode alterar o estimador passando uma função, que converte os dados em um valor
escalar.
[6]: sns.countplot(x='sex',data=tips)
boxplot() e violinplot() são usados para mostrar a distribuição dos dados categóricos.
Esses gráficos mostram a distribuição de dados quantitativos de uma maneira que facilita as
comparações entre variáveis ou entre os níveis de uma variável categórica.
catplot() é a forma mais geral de um gráfico categórico. Passamos pra ele um parâmetro
kind para escolher o tipo de gráfico.
[21]: sns.catplot(x='sex',y='total_bill',data=tips,kind='box')
[4]: tips.head()
[5]: flights.head()
6.4.1 Heatmap
Para que o heatmap (ou mapa de calor) funcione corretamente, seus dados já devem estar em
um formato de matriz, a função sns.heatmap() apenas os colore para você.
[6]: tips.head()
[8]: sns.heatmap(tips.corr())
[9]: sns.heatmap(tips.corr(),cmap='coolwarm',annot=True)
[10]: flights.pivot_table(values='passengers',index='month',columns='year')
[10]: year 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 ␣
,→1959 \
month
January 112 115 145 171 196 204 242 284 315 340 ␣
,→360
February 118 126 150 180 196 188 233 277 301 318 ␣
,→342
March 132 141 178 193 236 235 267 317 356 362 ␣
,→406
April 129 135 163 181 235 227 269 313 348 348 ␣
,→396
May 121 125 172 183 229 234 270 318 355 363 ␣
,→420
June 135 149 178 218 243 264 315 374 422 435 ␣
,→472
July 148 170 199 230 264 302 364 413 465 491 ␣
,→548
August 148 170 199 242 272 293 347 405 467 505 ␣
,→559
September 136 158 184 209 237 259 312 355 404 404 ␣
,→463
October 119 133 162 191 211 229 274 306 347 359 ␣
,→407
November 104 114 146 172 180 203 237 271 305 310 ␣
,→362
December 118 140 166 194 201 229 278 306 336 337 ␣
,→405
year 1960
month
January 417
February 391
March 419
134
April 461
May 472
June 535
July 622
August 606
September 508
October 461
November 390
December 432
sns.heatmap(pvflights)
[12]: sns.heatmap(pvflights,cmap='magma',linecolor='white',linewidths=1)
Vamos utilizar o conjunto de dados iris que contém medidas de partes de flores e suas
respectivas espécies
[3]: iris.head()
[7]: sns.pairplot(iris)
[8]: sns.pairplot(iris,hue='species',palette='rainbow')
[10]: tips.head()
[3]: tips.head()
146
lmplot() permite exibir modelos lineares, mas também convenientemente permite dividir
esses gráficos com base nos recursos.
[4]: sns.lmplot(x='total_bill',y='tip',data=tips)
[5]: sns.lmplot(x='total_bill',y='tip',data=tips,hue='sex')
147
[6]: sns.lmplot(x='total_bill',y='tip',data=tips,hue='sex',palette='coolwarm')
6.7.1 Marcadores
[7]: # http://matplotlib.org/api/markers_api.html
sns.lmplot(x='total_bill',y='tip',data=tips,hue='sex',palette='coolwarm',
markers=['o','v'],scatter_kws={'s':100})
Podemos tornar melhor a separação de variáveis através de colunas e linhas com o uso de uma
grade. Apenas indique isso com os argumentos col e/ou row.
[8]: sns.lmplot(x='total_bill',y='tip',data=tips,col='sex')
[10]: sns.
,→lmplot(x='total_bill',y='tip',data=tips,col='day',hue='sex',palette='coolwarm')
Seaborn pode ter seu tamanho e proporção ajustados com os parâmetros height e aspect:
152
[11]: sns.
,→lmplot(x='total_bill',y='tip',data=tips,col='day',hue='sex',palette='coolwarm',
aspect=0.6,height=8)
[2]: sns.countplot(x='sex',data=tips)
[3]: sns.set_style('darkgrid')
sns.countplot(x='sex',data=tips)
[4]: sns.set_style('dark')
sns.countplot(x='sex',data=tips,palette='deep')
[5]: sns.countplot(x='sex',data=tips)
sns.despine()
[6]: sns.countplot(x='sex',data=tips)
sns.despine(left=True)
155
[9]: sns.set_context('poster',font_scale=0.6)
sns.countplot(x='sex',data=tips,palette='coolwarm')
df1.head()
[2]: A B C D
2000-01-01 1.339091 -0.163643 -0.646443 1.041233
2000-01-02 -0.774984 0.137034 -0.882716 -2.253382
2000-01-03 -0.921037 -0.482943 -0.417100 0.478638
2000-01-04 -1.738808 -0.072973 0.056517 0.015085
2000-01-05 -0.905980 1.778576 0.381918 0.291436
O primeiro passo em toda exploração de dados é obter um histograma para ter ideia da
distribuição dos dados.
[3]: df1['A'].hist()
[5]: df1['A'].hist()
[6]: plt.style.use('bmh')
df1['A'].hist()
[7]: plt.style.use('dark_background')
df1['A'].hist()
[8]: plt.style.use('fivethirtyeight')
df1['A'].hist()
[9]: plt.style.use('ggplot')
[10]: df2.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10 entries, 0 to 9
162
[11]: df2.head()
[11]: a b c d
0 0.039762 0.218517 0.103423 0.957904
1 0.937288 0.041567 0.899125 0.977680
2 0.780504 0.008948 0.557808 0.797510
3 0.672717 0.247870 0.264071 0.444358
4 0.053829 0.520124 0.552264 0.190008
[12]: df2.plot.area(alpha=0.4)
[13]: df2.plot.bar()
163
[14]: df2.plot.bar(stacked=True)
[15]: df1['A'].plot.hist(bins=50)
[16]: df1.head()
[16]: A B C D
2000-01-01 1.339091 -0.163643 -0.646443 1.041233
2000-01-02 -0.774984 0.137034 -0.882716 -2.253382
2000-01-03 -0.921037 -0.482943 -0.417100 0.478638
2000-01-04 -1.738808 -0.072973 0.056517 0.015085
2000-01-05 -0.905980 1.778576 0.381918 0.291436
[17]: df1.plot.line(y='B',figsize=(12,3),lw=1)
[18]: df1.plot.scatter(x='A',y='B')
Você pode alterar a cor com o parâmetro c ou usar cmap para um mapa de cores.
[19]: df1.plot.scatter(x='A',y='B',c='C',cmap='coolwarm')
[20]: df1.plot.scatter(x='A',y='B',s=df1['C']*50)
C:\Users\jagapadi\AppData\Local\Continuum\anaconda3\envs\jupyter\lib\site-
packages\matplotlib\collections.py:857: RuntimeWarning: invalid value
encountered in sqrt
scale = np.sqrt(self._sizes) * dpi / 72.0 * self._factor
Kernel Density Estimation (KDE) é uma estimativa da distribuição da variável, cujo gráfico
é obtido de kde()
[23]: df2['a'].plot.kde()
[24]: df2.plot.density()
[2]: df3.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 500 entries, 0 to 499
Data columns (total 4 columns):
a 500 non-null float64
b 500 non-null float64
c 500 non-null float64
d 500 non-null float64
dtypes: float64(4)
memory usage: 15.8 KB
[3]: df3.head()
[3]: a b c d
0 0.336272 0.325011 0.001020 0.401402
1 0.980265 0.831835 0.772288 0.076485
2 0.480387 0.686839 0.000575 0.746758
3 0.502106 0.305142 0.768608 0.654685
4 0.856602 0.171448 0.157971 0.321231
[ ]:
[ ]:
[ ]:
171
[ ]:
[ ]:
172
%matplotlib inline
df.head()
[9]: a b c d
0 0.336272 0.325011 0.001020 0.401402
1 0.980265 0.831835 0.772288 0.076485
2 0.480387 0.686839 0.000575 0.746758
3 0.502106 0.305142 0.768608 0.654685
4 0.856602 0.171448 0.157971 0.321231
[10]: df.describe()
[10]: a b c d
count 500.000000 500.000000 500.000000 500.000000
mean 0.485294 0.504049 0.506183 0.517390
std 0.290985 0.272966 0.295953 0.293166
min 0.000410 0.010649 0.000575 0.002851
25% 0.225024 0.270928 0.243931 0.281738
50% 0.479164 0.510915 0.507474 0.533044
75% 0.755088 0.728839 0.769660 0.788106
max 0.998111 0.996740 0.999709 0.989946
173
[12]: df3['a'].plot.hist(bins=20)
[12]: <AxesSubplot:ylabel='Frequency'>
174
[13]: <AxesSubplot:>
175
[14]: df3['d'].plot.kde()
df3['d'].plot.hist(density=True, bins=15)
[14]: <AxesSubplot:ylabel='Frequency'>
[37]:
[ ]:
3. Crie um objeto do tipo figure e coloque dois axes no mesmo, localizados em [0, 0, 1, 1] e
[0.2, 0.5, .2, .2]. Então plote os mesmos dados em ambos.
[ ]:
[ ]:
178
[ ]: sns.set_style('whitegrid')
[ ]: titanic = sns.load_dataset('titanic')
[ ]: titanic.head()
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
7. Mostre um FacetGrid com dois histogramas das idades, um para cada sexo.
[ ]:
179
CATEGORIAS
IDENTIFICADOR DESCRIÇÃO
NOME CONTEÚDO DAS SEÇÕES 1, 2 e 3
PESO 60% DA NOTA
QUANTIDADE DE PERGUNTAS E RESPOSTAS 1
10 Conclusão
Obrigado por chegar ao final do nosso curso! Esperamos vocês nos próximos cursos, onde
veremos algoritmos mais complexos e aplicações mais próximos do estado da arte em Inteligência
Artificial, visão computacional e processamento de linguagem natural.
Gostaria de agradecer ao Davi Lobo de Melo autor da primeira versão dessa apostila.
181
Referências
[1] Anaconda. https://www.anaconda.com/, 2021. Acessado: 21-09-2021.