Tabelas e Tipos de Dados
Aprendendo como criar e manipular tabelas.
Resultados Esperados
- Aprender o básico de Pandas
- Entender diferentes tipos de dados
- Básico de filtros e seleções
- Aplicação de filtros básicos para gerar insights nos dados de dados tabulares
Sumário
Introdução
Neste notebook vamos explorar um pouco de dados tabulares, ou seja, tabelas. Tabelas de dados representam um dos tipos de dados mais comuns para o cientista de dados. Pense nas inúmeras tabelas Excell que você já trabalhou com.
A principal biblioteca para leitura de dados tabulares em Python se chama pandas. A mesma é bastante poderosa implementando uma série de operações de bancos de dados (e.g., groupby e join). Nossa discussão será focada em algumas das funções principais do pandas que vamos explorar no curso. Existe uma série ampla de funcionalidades que a biblioteca (além de outras) vai trazer.
Caso necessite de algo além da aula, busque na documentação da biblioteca. Por fim, durante esta aula, também vamos aprender um pouco de bash.
Imports básicos
A maioria dos nossos notebooks vai iniciar com os imports abaixo.
- pandas: dados tabulates
- matplotlib: gráficos e plots
A chamada plt.ion
habilita gráficos do matplotlib no notebook diretamente. Caso necesse salvar alguma figura, chame plt.savefig
após seu plot.
#In:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
Código de Configurar Plot (Oculto)
```python #In: plt.rcParams['figure.figsize'] = (16, 10) plt.rcParams['axes.axisbelow'] = True plt.rcParams['axes.grid'] = True plt.rcParams['axes.labelsize'] = 16 plt.rcParams['axes.linewidth'] = 2 plt.rcParams['axes.spines.bottom'] = True plt.rcParams['axes.spines.left'] = True plt.rcParams['axes.titlesize'] = 16 plt.rcParams['axes.ymargin'] = 0.1 plt.rcParams['font.family'] = 'serif' plt.rcParams['grid.color'] = 'lightgrey' plt.rcParams['grid.linewidth'] = .1 plt.rcParams['xtick.bottom'] = True plt.rcParams['xtick.direction'] = 'out' plt.rcParams['xtick.labelsize'] = 16 plt.rcParams['xtick.major.size'] = 12 plt.rcParams['xtick.major.width'] = 1 plt.rcParams['xtick.minor.size'] = 6 plt.rcParams['xtick.minor.width'] = 1 plt.rcParams['xtick.minor.visible'] = True plt.rcParams['ytick.direction'] = 'out' plt.rcParams['ytick.labelsize'] = 16 plt.rcParams['ytick.left'] = True plt.rcParams['ytick.major.size'] = 12 plt.rcParams['ytick.major.width'] = 1 plt.rcParams['ytick.minor.size'] = 6 plt.rcParams['ytick.minor.width'] = 1 plt.rcParams['ytick.minor.visible'] = True plt.rcParams['legend.fontsize'] = 16 plt.rcParams['lines.linewidth'] = 4 plt.rcParams['lines.markersize'] = 80 ``` ```python #In: plt.style.use('tableau-colorblind10') plt.ion(); ```Series
Existem dois tipos base de dados em pandas. O primeiro, Series, representa uma coluna de dados. Um combinação de Series vira um DataFrame (mais abaixo). Diferente de um vetor numpy
, a Series de panda captura uma coluna de dados (ou vetor) indexado. Isto é, podemos nomear cada um dos valores.
#In:
data = pd.Series(
[0.25, 0.5, 0.75, 1.0],
index=['a', 'b', 'c', 'd']
)
#In:
data
a 0.25
b 0.50
c 0.75
d 1.00
dtype: float64
Note que podemos usar como um vetor
#In:
data[0]
0.25
Porém o índice nos ajuda. Para um exemplo trivial como este não será tão interessante, mas vamos usar o mesmo.
#In:
data.index
Index(['a', 'b', 'c', 'd'], dtype='object')
Com .loc acessamos uma linha do índice com base no nome. Então:
series.loc[objeto_python]
- valor com o devido nome.series.iloc[int]
- i-ésimo elemento da Series.
#In:
data.loc['a']
0.25
#In:
data.loc['b']
0.5
Com iloc
acessamos por número da linha, estilho um vetor.
#In:
data.iloc[0]
0.25
#In:
data[0]
0.25
Data Frames
Ao combinar várias Series com um índice comum, criamos um DataFrame. Não é tão comum gerar os mesmos na mão como estamos fazendo, geralmente carregamos DataFrames de arquivos .csv
, .json
ou até de sistemas de bancos de dados mariadb
. De qualquer forma, use os exemplos abaixo para entender a estrutura de um dataframe.
Lembre-se que {}/dict é um dicionário (ou mapa) em Python. Podemos criar uma série a partir de um dicionário index->value
#In:
area_dict = {'California': 423967,
'Texas': 695662,
'New York': 141297,
'Florida': 170312,
'Illinois': 149995}
A linha abaixo pega todas as chaves.
#In:
list(area_dict.keys())
['California', 'Texas', 'New York', 'Florida', 'Illinois']
Agora todas as colunas
#In:
list(area_dict.values())
[423967, 695662, 141297, 170312, 149995]
Acessando um valor.
#In:
area_dict['California']
423967
Podemos criar a série a partir do dicionário, cada chave vira um elemento do índice. Os valores viram os dados do vetor.
#In:
area = pd.Series(area_dict)
area
California 423967
Texas 695662
New York 141297
Florida 170312
Illinois 149995
dtype: int64
Agora, vamos criar outro dicionário com a população dos estados.
#In:
pop_dict = {'California': 38332521,
'Texas': 26448193,
'New York': 19651127,
'Florida': 19552860,
'Illinois': 12882135}
pop = pd.Series(pop_dict)
pop
California 38332521
Texas 26448193
New York 19651127
Florida 19552860
Illinois 12882135
dtype: int64
Por fim, observe que o DataFrame é uma combinação de Series. Cada uma das Series vira uma coluna da tabela de dados.
#In:
data = pd.DataFrame({'area':area, 'pop':pop})
data
area | pop | |
---|---|---|
California | 423967 | 38332521 |
Texas | 695662 | 26448193 |
New York | 141297 | 19651127 |
Florida | 170312 | 19552860 |
Illinois | 149995 | 12882135 |
Agora o use de .loc e .iloc
deve ficar mais claro, observe os exemplos abaixo.
#In:
data.loc['California']
area 423967
pop 38332521
Name: California, dtype: int64
#In:
data.loc[['California', 'Texas']]
area | pop | |
---|---|---|
California | 423967 | 38332521 |
Texas | 695662 | 26448193 |
Note que o uso de iloc
retorna a i-ésima linha. O problema é que nem sempre nos dataframes esta ordem vai fazer sentido. O iloc
acaba sendo mais interessante para iteração (e.g., passar por todas as linhas.)
#In:
data.iloc[0]
area 423967
pop 38332521
Name: California, dtype: int64
Slicing
Agora, podemos realizar slicing no DataFrame. Slicing é uma operação Python que retorna sub-listas/sub-vetores. Caso não conheça, tente executar o exemplo abaixo:
#In:
l = []
l = [7, 1, 3, 5, 9]
print(l[0])
print(l[1])
print(l[2])
# Agora, l[bg:ed] retorna uma sublista iniciando em bg e terminando em ed-1
print(l[1:4])
#In:
l = []
l = [7, 1, 3, 5, 9]
print(l[0])
print(l[1])
print(l[2])
# Agora, l[bg:ed] retorna uma sublista iniciando em bg e terminando em ed-1
print(l[1:4])
7
1
3
[1, 3, 5]
Voltando para o nosso dataframe, podemos realizar o slicing usando o .iloc
.
#In:
data.iloc[2:4]
area | pop | |
---|---|---|
New York | 141297 | 19651127 |
Florida | 170312 | 19552860 |
Modificando DataFrames
Series e DataFrames são objetos mutáveis em Python. Podemos adicionar novas colunas em DataFrama facilmente da mesma forma que adicionamos novos valores em um mapa. Por fim, podemos também mudar o valor de linhas específicas e adicionar novas linhas.
#In:
data['density'] = data['pop'] / data['area']
data.loc['Texas']
area 6.956620e+05
pop 2.644819e+07
density 3.801874e+01
Name: Texas, dtype: float64
#In:
df = data
#In:
df.index
Index(['California', 'Texas', 'New York', 'Florida', 'Illinois'], dtype='object')
Arquivos
Antes de explorar DataFrames em arquivos, vamos ver como um notebook na é um shell bastante poderoso. Ao usar uma exclamação (!) no notebook Jupyter, conseguimos executar comandos do shell do sistema. Em particular, aqui estamos executando o comando ls para indentificar os dados da pasta atual.
Tudo que executamos com !
é um comando do terminal do unix. Então, este notebook só deve executar as linhas abaixo em um Mac
ou Linux
.
#In:
!ls .
01-causalidade.md 15-linear
02-tabelas 15-linear_files
02-tabelas.ipynb 15-linear.ipynb
02-tabelas.md 15-linear.md
03-viz 16-vero
03-viz_files 16-vero_files
03-viz.ipynb 16-vero.ipynb
03-viz.md 16-vero.md
04-stat 17-gradiente
04-stat_files 17-gradiente_files
04-stat.ipynb 17-gradiente.ipynb
04-stat.md 17-gradiente.md
05-prob 18-multipla
05-prob_files 18-multipla_files
05-prob.ipynb 18-multipla.ipynb
05-prob.md 18-multipla.md
06-risco 19-logistica
06-risco_files 19-logistica_files
06-risco.ipynb 19-logistica.ipynb
06-risco.md 19-logistica.md
07-tcl 20-knn
07-tcl_files 20-knn_files
07-tcl.ipynb 20-knn.ipynb
07-tcl.md 20-knn.md
08-amostragem 21-pratica
08-amostragem_files 21-pratica_files
08-amostragem.ipynb 21-pratica.ipynb
08-amostragem.md 21-pratica.md
09-ics 22-svd-e-pca
09-ics_files 22-svd-e-pca_files
09-ics.ipynb 22-svd-e-pca.ipynb
09-ics.md 22-svd-e-pca.md
10-ab 26b-tutorial-sklearn-classification.ipynb
10-ab_files 26-tutorial-sklearn-regressao.ipynb
10-ab.ipynb 27-revisao
10-ab.md 27-revisao_files
11-hipoteses 27-revisao.ipynb
11-hipoteses_files 27-revisao.md
11-hipoteses.ipynb baby.csv
11-hipoteses.md capital.json
12-causalidade colab_favicon.ico
12-causalidade_files colab_favicon.png
12-causalidade.ipynb colab_favicon_small.png
12-causalidade.md compile_all.sh
13-poder compile_notebook.sh
13-poder_files dom-casmurro.txt
13-poder.ipynb drum.wav
13-poder.md f2.png
14-correlacao f.png
14-correlacao_files proglanguages.json
14-correlacao.ipynb states.txt
14-correlacao.md walmart.csv
Com a opção -lha, mostramos meta-dados dos arquivos como o owner, tamanho e permissões. Note que todos os arquivos são .csv, isto é comma separated.
#In:
! ls -lha .
total 180M
drwxr-xr-x 46 flaviovdf flaviovdf 4.0K Mar 21 18:36 .
drwxr-xr-x 9 flaviovdf flaviovdf 4.0K Mar 14 18:52 ..
-rw-r--r-- 1 flaviovdf flaviovdf 618 Mar 14 18:20 01-causalidade.md
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 21 18:19 02-tabelas
-rw-r--r-- 1 flaviovdf flaviovdf 107K Mar 21 18:36 02-tabelas.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 49K Mar 21 18:16 02-tabelas.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 21 18:36 03-viz
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 21 18:36 03-viz_files
-rw-r--r-- 1 flaviovdf flaviovdf 1.2M Mar 21 18:36 03-viz.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 40K Mar 21 18:36 03-viz.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 04-stat
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 04-stat_files
-rw-r--r-- 1 flaviovdf flaviovdf 360K Mar 14 18:20 04-stat.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 26K Mar 14 18:20 04-stat.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 05-prob
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 05-prob_files
-rw-r--r-- 1 flaviovdf flaviovdf 892K Mar 14 18:20 05-prob.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 35K Mar 14 18:20 05-prob.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 06-risco
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 06-risco_files
-rw-r--r-- 1 flaviovdf flaviovdf 291K Mar 14 18:20 06-risco.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 15K Mar 14 18:20 06-risco.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 07-tcl
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 07-tcl_files
-rw-r--r-- 1 flaviovdf flaviovdf 445K Mar 14 18:20 07-tcl.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 14K Mar 14 18:20 07-tcl.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 08-amostragem
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 08-amostragem_files
-rw-r--r-- 1 flaviovdf flaviovdf 232K Mar 14 18:20 08-amostragem.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 117K Mar 14 18:20 08-amostragem.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 09-ics
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 09-ics_files
-rw-r--r-- 1 flaviovdf flaviovdf 692K Mar 14 18:20 09-ics.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 91K Mar 14 18:20 09-ics.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 10-ab
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 10-ab_files
-rw-r--r-- 1 flaviovdf flaviovdf 172K Mar 14 18:20 10-ab.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 17K Mar 14 18:20 10-ab.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 11-hipoteses
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 11-hipoteses_files
-rw-r--r-- 1 flaviovdf flaviovdf 301K Mar 14 18:20 11-hipoteses.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 94K Mar 14 18:20 11-hipoteses.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 12-causalidade
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 12-causalidade_files
-rw-r--r-- 1 flaviovdf flaviovdf 52K Mar 14 18:20 12-causalidade.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 9.6K Mar 14 18:20 12-causalidade.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 13-poder
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 13-poder_files
-rw-r--r-- 1 flaviovdf flaviovdf 837K Mar 14 18:20 13-poder.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 25K Mar 14 18:20 13-poder.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 14-correlacao
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 14-correlacao_files
-rw-r--r-- 1 flaviovdf flaviovdf 1.8M Mar 14 18:20 14-correlacao.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 39K Mar 14 18:20 14-correlacao.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 15-linear
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 15-linear_files
-rw-r--r-- 1 flaviovdf flaviovdf 992K Mar 14 18:20 15-linear.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 25K Mar 14 18:20 15-linear.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 16-vero
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 16-vero_files
-rw-r--r-- 1 flaviovdf flaviovdf 1.0M Mar 14 18:20 16-vero.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 30K Mar 14 18:20 16-vero.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 17-gradiente
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 17-gradiente_files
-rw-r--r-- 1 flaviovdf flaviovdf 731K Mar 14 18:20 17-gradiente.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 58K Mar 14 18:20 17-gradiente.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 18-multipla
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 18-multipla_files
-rw-r--r-- 1 flaviovdf flaviovdf 671K Mar 14 18:20 18-multipla.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 136K Mar 14 18:20 18-multipla.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 19-logistica
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 19-logistica_files
-rw-r--r-- 1 flaviovdf flaviovdf 886K Mar 14 18:20 19-logistica.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 79K Mar 14 18:20 19-logistica.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 20-knn
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 20-knn_files
-rw-r--r-- 1 flaviovdf flaviovdf 790K Mar 14 18:20 20-knn.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 19K Mar 14 18:20 20-knn.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 21-pratica
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 21-pratica_files
-rw-r--r-- 1 flaviovdf flaviovdf 280K Mar 14 18:20 21-pratica.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 72K Mar 14 18:20 21-pratica.md
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 22-svd-e-pca
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 22-svd-e-pca_files
-rw-r--r-- 1 flaviovdf flaviovdf 9.5M Mar 14 18:20 22-svd-e-pca.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 6.7M Mar 14 18:20 22-svd-e-pca.md
-rw-r--r-- 1 flaviovdf flaviovdf 47K Mar 14 18:20 26b-tutorial-sklearn-classification.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 203K Mar 14 18:20 26-tutorial-sklearn-regressao.ipynb
drwxr-xr-x 3 flaviovdf flaviovdf 4.0K Mar 14 18:20 27-revisao
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 27-revisao_files
-rw-r--r-- 1 flaviovdf flaviovdf 63K Mar 14 18:20 27-revisao.ipynb
-rw-r--r-- 1 flaviovdf flaviovdf 17K Mar 14 18:20 27-revisao.md
-rw-r--r-- 1 flaviovdf flaviovdf 148M Mar 21 18:02 baby.csv
-rw-r--r-- 1 flaviovdf flaviovdf 172K Mar 14 18:20 capital.json
-rw-r--r-- 1 flaviovdf flaviovdf 72K Mar 14 18:20 colab_favicon.ico
-rw-r--r-- 1 flaviovdf flaviovdf 7.8K Mar 14 18:20 colab_favicon.png
-rw-r--r-- 1 flaviovdf flaviovdf 2.2K Mar 14 18:20 colab_favicon_small.png
-rw-r--r-- 1 flaviovdf flaviovdf 85 Mar 14 18:20 compile_all.sh
-rw-r--r-- 1 flaviovdf flaviovdf 1.1K Mar 14 18:20 compile_notebook.sh
-rw-r--r-- 1 flaviovdf flaviovdf 401K Mar 14 18:20 dom-casmurro.txt
-rw-r--r-- 1 flaviovdf flaviovdf 331K Mar 14 18:20 drum.wav
-rw-r--r-- 1 flaviovdf flaviovdf 125K Mar 14 18:20 f2.png
-rw-r--r-- 1 flaviovdf flaviovdf 57K Mar 14 18:20 f.png
drwxr-xr-x 2 flaviovdf flaviovdf 4.0K Mar 14 18:20 .ipynb_checkpoints
-rw-r--r-- 1 flaviovdf flaviovdf 29K Mar 14 18:20 .nbgrader.log
-rw-r--r-- 1 flaviovdf flaviovdf 3.1K Mar 14 18:20 proglanguages.json
-rw-r--r-- 1 flaviovdf flaviovdf 131K Mar 14 18:20 states.txt
-rw-r--r-- 1 flaviovdf flaviovdf 715K Mar 14 18:20 walmart.csv
Vamos identificar qual a cara de um csv. O programa head
imprime as primeiras n
linhas de um arquivo.
#In:
! head baby.csv
Id,Name,Year,Gender,State,Count
1,Mary,1910,F,AK,14
2,Annie,1910,F,AK,12
3,Anna,1910,F,AK,10
4,Margaret,1910,F,AK,8
5,Helen,1910,F,AK,7
6,Elsie,1910,F,AK,6
7,Lucy,1910,F,AK,6
8,Dorothy,1910,F,AK,5
9,Mary,1911,F,AK,12
Observe como o comando head
nos ajuda a entender o arquivo .csv
. Sabemos quais colunas e qual o separador do mesmo.
Baby Names
É bem mais comum fazer uso de DataFrames que já existem em arquivos. Note que o trabalho do cientista de dados nem sempre vai ter tais arquivos prontos. Em várias ocasiões, você vai ter que coletar e organizar os mesmos. Limpeza e coleta de dados é uma parte fundamental do seu trabalho. Durante a matéria, boa parte dos notebooks já vão ter dados prontos.
#In:
df = pd.read_csv('https://media.githubusercontent.com/media/icd-ufmg/material/master/aulas/03-Tabelas-e-Tipos-de-Dados/baby.csv')
df = df.drop('Id', axis='columns') # remove a coluna id, serve de nada
df
Name | Year | Gender | State | Count | |
---|---|---|---|---|---|
0 | Mary | 1910 | F | AK | 14 |
1 | Annie | 1910 | F | AK | 12 |
2 | Anna | 1910 | F | AK | 10 |
3 | Margaret | 1910 | F | AK | 8 |
4 | Helen | 1910 | F | AK | 7 |
... | ... | ... | ... | ... | ... |
5647421 | Seth | 2014 | M | WY | 5 |
5647422 | Spencer | 2014 | M | WY | 5 |
5647423 | Tyce | 2014 | M | WY | 5 |
5647424 | Victor | 2014 | M | WY | 5 |
5647425 | Waylon | 2014 | M | WY | 5 |
5647426 rows × 5 columns
O método head
do notebook retorna as primeiras n
linhas do mesmo. Use tal método para entender seus dados. Sempre olhe para seus dados. Note como as linhas abaixo usa o loc
e iloc
para entender um pouco a estrutura dos mesmos.
#In:
df.head()
Name | Year | Gender | State | Count | |
---|---|---|---|---|---|
0 | Mary | 1910 | F | AK | 14 |
1 | Annie | 1910 | F | AK | 12 |
2 | Anna | 1910 | F | AK | 10 |
3 | Margaret | 1910 | F | AK | 8 |
4 | Helen | 1910 | F | AK | 7 |
O método head
do notebook retorna as primeiras n
linhas do mesmo. Use tal método para entender seus dados. Sempre olhe para seus dados. Note como as linhas abaixo usa o loc
e iloc
para entender um pouco a estrutura dos mesmos.
#In:
df.head(6)
Name | Year | Gender | State | Count | |
---|---|---|---|---|---|
0 | Mary | 1910 | F | AK | 14 |
1 | Annie | 1910 | F | AK | 12 |
2 | Anna | 1910 | F | AK | 10 |
3 | Margaret | 1910 | F | AK | 8 |
4 | Helen | 1910 | F | AK | 7 |
5 | Elsie | 1910 | F | AK | 6 |
#In:
df[10:15]
Name | Year | Gender | State | Count | |
---|---|---|---|---|---|
10 | Ruth | 1911 | F | AK | 7 |
11 | Annie | 1911 | F | AK | 6 |
12 | Elizabeth | 1911 | F | AK | 6 |
13 | Helen | 1911 | F | AK | 6 |
14 | Mary | 1912 | F | AK | 9 |
#In:
df.iloc[0:6]
Name | Year | Gender | State | Count | |
---|---|---|---|---|---|
0 | Mary | 1910 | F | AK | 14 |
1 | Annie | 1910 | F | AK | 12 |
2 | Anna | 1910 | F | AK | 10 |
3 | Margaret | 1910 | F | AK | 8 |
4 | Helen | 1910 | F | AK | 7 |
5 | Elsie | 1910 | F | AK | 6 |
#In:
df[['Name', 'Gender']].head(6)
Name | Gender | |
---|---|---|
0 | Mary | F |
1 | Annie | F |
2 | Anna | F |
3 | Margaret | F |
4 | Helen | F |
5 | Elsie | F |
#In:
df[['Name', 'Gender']].head(6)
Name | Gender | |
---|---|---|
0 | Mary | F |
1 | Annie | F |
2 | Anna | F |
3 | Margaret | F |
4 | Helen | F |
5 | Elsie | F |
Groupby
Vamos responder algumas perguntas com a função groupby. Lembrando a ideia é separar os dados com base em valores comuns, ou seja, agrupar por nomes e realizar alguma operação. O comando abaixo agrupa todos os recem-náscidos por nome. Imagine a mesma fazendo uma operação equivalente ao laço abaixo:
#In:
buckets = {} # Mapa de dados
names = set(df['Name']) # Conjunto de nomes únicos
for idx, row in df.iterrows(): # Para cada linha dos dados
name = row['Name']
if name not in buckets:
buckets[name] = [] # Uma lista para cada nome
buckets[name].append(row) # Separa a linha para cada nome
O código acima é bastante lento!!! O groupby é optimizado. Com base na linha abaixo, o mesmo nem retorna nehum resultado ainda. Apenas um objeto onde podemos fazer agregações.
#In:
gb = df.groupby('Name')
type(gb)
pandas.core.groupby.generic.DataFrameGroupBy
Agora posso agregar todos os nomes com alguma operação. Por exemplo, posso somar a quantidade de vezes que cada nome ocorre. Em python, seria o seguinte código.
#In:
sum_ = {} # Mapa de dados
for name in buckets: # Para cada nomee
sum_[name] = 0
for row in buckets[name]: # Para cada linha com aquele nome, aggregate (some)
sum_[name] += row['Count']
Observe o resultado da agregação abaixo. Qual o problema com a coluna Year
??
#In:
gb[['Year', 'Count']].mean()
Year | Count | |
---|---|---|
Name | ||
Aaban | 2013.500000 | 6.000000 |
Aadan | 2009.750000 | 5.750000 |
Aadarsh | 2009.000000 | 5.000000 |
Aaden | 2010.015306 | 17.479592 |
Aadhav | 2014.000000 | 6.000000 |
... | ... | ... |
Zyrah | 2012.000000 | 5.500000 |
Zyren | 2013.000000 | 6.000000 |
Zyria | 2006.714286 | 5.785714 |
Zyriah | 2009.666667 | 6.444444 |
Zyshonne | 1998.000000 | 5.000000 |
30274 rows × 2 columns
Não faz tanto sentido somar o ano, embora seja um número aqui representa uma categoria. Vamos somar as contagens apenas.
Observe como a chamada abaixo tem um enter depois de cada ponto. Isso é um truque para deixar o código mais legível
#In:
# Leia dessa forma
(dados[['coluna1', 'coluna2']]. # selecione algumas colunas
operacao_a(). # realize uma operação
operacao_b() # realize outra
)
# É o mesmo de
dados[['coluna1', 'coluna2']].operacao_a().operacao_b()
Cada chamada pandas retorna um DataFrame novo. Ao fazer .
chamamos um novo método. Quebrando a linha no ponto fica mais fácil separa a lógica de cada operação. Compare os casos abaixo.
#In:
# Leia dessa forma
(dados[['coluna1', 'coluna2']]. # selecione algumas colunas
operacao_a(). # realize uma operação
operacao_b(). # realize outra
operaca_c().
operaca_d().
operaca_e().
operaca_f().
)
# É o mesmo de
dados[['coluna1', 'coluna2']].operacao_a().operacao_c().operacao_d().operacao_e().operacao_f()
#In:
(gb['Count'].
sum().
sort_values()
)
Name
Zyshonne 5
Makenlee 5
Makenlie 5
Makinlee 5
Makua 5
...
William 3839236
Michael 4312975
Robert 4725713
John 4845414
James 4957166
Name: Count, Length: 30274, dtype: int64
E ordenar…
#In:
(gb['Count'].
sum().
sort_values()
)
Name
Zyshonne 5
Makenlee 5
Makenlie 5
Makinlee 5
Makua 5
...
William 3839236
Michael 4312975
Robert 4725713
John 4845414
James 4957166
Name: Count, Length: 30274, dtype: int64
É comum, embora mais chato de ler, fazer tudo em uma única chamada. Isto é uma prática que vem do mundo SQL. A chamada abaixo seria o mesmo de:
SELECT Name, SUM(Count)
FROM baby_table
GROUPBY Name
ORDERBY SUM(Count)
#In:
(df[['Name', 'Count']].
groupby('Name').
sum().
sort_values(by='Count')
)
Count | |
---|---|
Name | |
Zyshonne | 5 |
Makenlee | 5 |
Makenlie | 5 |
Makinlee | 5 |
Makua | 5 |
... | ... |
William | 3839236 |
Michael | 4312975 |
Robert | 4725713 |
John | 4845414 |
James | 4957166 |
30274 rows × 1 columns
#In:
(df[['Name', 'Year', 'Count']].
groupby(['Name', 'Year']).
sum()
)
Count | ||
---|---|---|
Name | Year | |
Aaban | 2013 | 6 |
2014 | 6 | |
Aadan | 2008 | 12 |
2009 | 6 | |
2014 | 5 | |
... | ... | ... |
Zyriah | 2011 | 6 |
2012 | 5 | |
2013 | 7 | |
2014 | 6 | |
Zyshonne | 1998 | 5 |
548154 rows × 1 columns
NBA Salaries e Indexação Booleana
Por fim, vamos explorar alguns dados da NBA para entender a indexação booleana. Vamos carregar os dados da mesma forma que carregamos os dados dos nomes de crianças.
#In:
df = pd.read_csv('https://media.githubusercontent.com/media/icd-ufmg/material/master/aulas/03-Tabelas-e-Tipos-de-Dados/nba_salaries.csv')
df.head()
PLAYER | POSITION | TEAM | SALARY | |
---|---|---|---|---|
0 | Paul Millsap | PF | Atlanta Hawks | 18.671659 |
1 | Al Horford | C | Atlanta Hawks | 12.000000 |
2 | Tiago Splitter | C | Atlanta Hawks | 9.756250 |
3 | Jeff Teague | PG | Atlanta Hawks | 8.000000 |
4 | Kyle Korver | SG | Atlanta Hawks | 5.746479 |
Por fim, vamos indexar nosso DataFrame por booleanos. A linha abaixo pega um vetor de booleanos onde o nome do time é Houston Rockets
.
#In:
df['TEAM'] == 'Houston Rockets'
0 False
1 False
2 False
3 False
4 False
...
412 False
413 False
414 False
415 False
416 False
Name: TEAM, Length: 417, dtype: bool
Podemos usar tal vetor para filtrar nosso DataFrame. A linha abaixo é o mesmo de um:
SELECT *
FROM table
WHERE TEAM = 'Houston Rockets'
#In:
filtro = df['TEAM'] == 'Houston Rockets'
df[filtro]
PLAYER | POSITION | TEAM | SALARY | |
---|---|---|---|---|
131 | Dwight Howard | C | Houston Rockets | 22.359364 |
132 | James Harden | SG | Houston Rockets | 15.756438 |
133 | Ty Lawson | PG | Houston Rockets | 12.404495 |
134 | Corey Brewer | SG | Houston Rockets | 8.229375 |
135 | Trevor Ariza | SF | Houston Rockets | 8.193030 |
136 | Patrick Beverley | PG | Houston Rockets | 6.486486 |
137 | K.J. McDaniels | SG | Houston Rockets | 3.189794 |
138 | Terrence Jones | PF | Houston Rockets | 2.489530 |
139 | Donatas Motiejunas | PF | Houston Rockets | 2.288205 |
140 | Sam Dekker | SF | Houston Rockets | 1.646400 |
141 | Clint Capela | PF | Houston Rockets | 1.242720 |
142 | Montrezl Harrell | PF | Houston Rockets | 1.000000 |
Assim como pegar os salários maior do que um certo valor!
#In:
df[df['SALARY'] > 20]
PLAYER | POSITION | TEAM | SALARY | |
---|---|---|---|---|
29 | Joe Johnson | SF | Brooklyn Nets | 24.894863 |
60 | Derrick Rose | PG | Chicago Bulls | 20.093064 |
72 | LeBron James | SF | Cleveland Cavaliers | 22.970500 |
131 | Dwight Howard | C | Houston Rockets | 22.359364 |
156 | Chris Paul | PG | Los Angeles Clippers | 21.468695 |
169 | Kobe Bryant | SF | Los Angeles Lakers | 25.000000 |
201 | Chris Bosh | PF | Miami Heat | 22.192730 |
255 | Carmelo Anthony | SF | New York Knicks | 22.875000 |
268 | Kevin Durant | SF | Oklahoma City Thunder | 20.158622 |
Exercícios
Abaixo temos algumas chamadas em pandas. Tente explicar cada uma delas.
#In:
(df[['POSITION', 'SALARY']].
groupby('POSITION').
mean()
)
SALARY | |
---|---|
POSITION | |
C | 6.082913 |
PF | 4.951344 |
PG | 5.165487 |
SF | 5.532675 |
SG | 3.988195 |
#In:
(df[['TEAM', 'SALARY']].
groupby('TEAM').
mean().
sort_values('SALARY')
)
SALARY | |
---|---|
TEAM | |
Phoenix Suns | 2.971813 |
Utah Jazz | 3.095993 |
Portland Trail Blazers | 3.246206 |
Philadelphia 76ers | 3.267796 |
Boston Celtics | 3.352367 |
Milwaukee Bucks | 4.019873 |
Detroit Pistons | 4.221176 |
Toronto Raptors | 4.392507 |
Brooklyn Nets | 4.408229 |
Denver Nuggets | 4.459243 |
Memphis Grizzlies | 4.466497 |
Charlotte Hornets | 4.672355 |
Indiana Pacers | 4.822694 |
Atlanta Hawks | 4.969507 |
New Orleans Pelicans | 5.032163 |
Minnesota Timberwolves | 5.065186 |
Los Angeles Clippers | 5.082624 |
Washington Wizards | 5.296912 |
New York Knicks | 5.338846 |
Orlando Magic | 5.544567 |
Dallas Mavericks | 5.978414 |
Oklahoma City Thunder | 6.052010 |
Sacramento Kings | 6.216808 |
Los Angeles Lakers | 6.237086 |
San Antonio Spurs | 6.511698 |
Chicago Bulls | 6.568407 |
Golden State Warriors | 6.720367 |
Miami Heat | 6.794056 |
Houston Rockets | 7.107153 |
Cleveland Cavaliers | 10.231241 |