Manipulação de dados - II¶
DataFrames¶
Como dissemos anterioremente, o DataFrame é a segunda estrutura basilar do pandas. Um DataFrame:
é uma tabela, ou seja, é bidimensional;
tem cada coluna formada como uma Series do pandas;
pode ter Series contendo tipos de dado diferentes.
import numpy as np
import pandas as pd
Criação de um DataFrame¶
O método padrão para criarmos um DataFrame é através de uma função com mesmo nome.
df_exemplo = pd.DataFrame(dados_de_interesse, index = indice_de_interesse, 
                          columns = colunas_de_interesse)
Ao criar um DataFrame, podemos informar
index: rótulos para as linhas (atributos index das Series).columns: rótulos para as colunas (atributos name das Series).
No template, dados_de_interesse pode ser
um dicionário de:
arrays unidimensionais do numpy;
listas;
dicionários;
Series do pandas.
um array bidimensional do numpy;
uma Series do Pandas;
outro DataFrame.
DataFrame a partir de dicionários de Series¶
Neste método de criação, as Series do dicionário não precisam possuir o mesmo número de elementos. O index do DataFrame será dado pela união dos index de todas as Series contidas no dicionário.
Exemplo:
serie_Idade = pd.Series({'Ana':20, 'João': 19, 'Maria': 21, 'Pedro': 22}, name="Idade")
serie_Peso = pd.Series({'Ana':55, 'João': 80, 'Maria': 62, 'Pedro': 67, 'Túlio': 73}, name="Peso")
serie_Altura = pd.Series({'Ana':162, 'João': 178, 'Maria': 162, 'Pedro': 165, 'Túlio': 171}, name="Altura")
dicionario_series_exemplo = {'Idade': serie_Idade, 'Peso': serie_Peso, 'Altura': serie_Altura}
df_dict_series = pd.DataFrame(dicionario_series_exemplo)
df_dict_series
| Idade | Peso | Altura | |
|---|---|---|---|
| Ana | 20.0 | 55 | 162 | 
| João | 19.0 | 80 | 178 | 
| Maria | 21.0 | 62 | 162 | 
| Pedro | 22.0 | 67 | 165 | 
| Túlio | NaN | 73 | 171 | 
Compare este resultado com a criação de uma planilha pelos métodos usuais. Veja que há muita flexibilidade para criarmos ou modificarmos uma tabela.
Vejamos exemplos sobre como acessar intervalos de dados na tabela.
pd.DataFrame(dicionario_series_exemplo, index=['Ana','Maria'])
| Idade | Peso | Altura | |
|---|---|---|---|
| Ana | 20 | 55 | 162 | 
| Maria | 21 | 62 | 162 | 
pd.DataFrame(dicionario_series_exemplo, index=['Ana','Maria'], columns=['Peso','Altura'])
| Peso | Altura | |
|---|---|---|
| Ana | 55 | 162 | 
| Maria | 62 | 162 | 
Neste exemplo, adicionamos a coluna IMC, ainda sem valores calculados.
pd.DataFrame(dicionario_series_exemplo, index=['Ana','Maria','Paula'], 
             columns=['Peso','Altura','IMC'])
| Peso | Altura | IMC | |
|---|---|---|---|
| Ana | 55.0 | 162.0 | NaN | 
| Maria | 62.0 | 162.0 | NaN | 
| Paula | NaN | NaN | NaN | 
df_exemplo_IMC = pd.DataFrame(dicionario_series_exemplo, 
             columns=['Peso','Altura','IMC'])
Agora, mostramos como os valores do IMC podem ser calculados diretamente por computação vetorizada sobre as Series.
df_exemplo_IMC['IMC']=round(df_exemplo_IMC['Peso']/(df_exemplo_IMC['Altura']/100)**2,2)
df_exemplo_IMC
| Peso | Altura | IMC | |
|---|---|---|---|
| Ana | 55 | 162 | 20.96 | 
| João | 80 | 178 | 25.25 | 
| Maria | 62 | 162 | 23.62 | 
| Pedro | 67 | 165 | 24.61 | 
| Túlio | 73 | 171 | 24.96 | 
DataFrame a partir de dicionários de listas ou arrays do numpy¶
Neste método de criação, os arrays ou as listas devem possuir o mesmo comprimento. Se o index não for informado, o index será dado de forma similar ao do objeto tipo Series.
Exemplo com dicionário de listas:
dicionario_lista_exemplo = {'Idade': [20,19,21,22,20],
                            'Peso': [55,80,62,67,73],
                            'Altura': [162,178,162,165,171]}
pd.DataFrame(dicionario_lista_exemplo)
| Idade | Peso | Altura | |
|---|---|---|---|
| 0 | 20 | 55 | 162 | 
| 1 | 19 | 80 | 178 | 
| 2 | 21 | 62 | 162 | 
| 3 | 22 | 67 | 165 | 
| 4 | 20 | 73 | 171 | 
Mais exemplos:
pd.DataFrame(dicionario_lista_exemplo, index=['Ana','João','Maria','Pedro','Túlio'])
| Idade | Peso | Altura | |
|---|---|---|---|
| Ana | 20 | 55 | 162 | 
| João | 19 | 80 | 178 | 
| Maria | 21 | 62 | 162 | 
| Pedro | 22 | 67 | 165 | 
| Túlio | 20 | 73 | 171 | 
Exemplos com dicionário de arrays do numpy:
dicionario_array_exemplo = {'Idade': np.array([20,19,21,22,20]),
                            'Peso': np.array([55,80,62,67,73]),
                            'Altura': np.array([162,178,162,165,171])}
pd.DataFrame(dicionario_array_exemplo)
| Idade | Peso | Altura | |
|---|---|---|---|
| 0 | 20 | 55 | 162 | 
| 1 | 19 | 80 | 178 | 
| 2 | 21 | 62 | 162 | 
| 3 | 22 | 67 | 165 | 
| 4 | 20 | 73 | 171 | 
Mais exemplos:
pd.DataFrame(dicionario_array_exemplo, index=['Ana','João','Maria','Pedro','Túlio'])
| Idade | Peso | Altura | |
|---|---|---|---|
| Ana | 20 | 55 | 162 | 
| João | 19 | 80 | 178 | 
| Maria | 21 | 62 | 162 | 
| Pedro | 22 | 67 | 165 | 
| Túlio | 20 | 73 | 171 | 
DataFrame a partir de uma Series do pandas¶
Neste caso, o DataFrame terá o mesmo index que a Series do pandas e apenas uma coluna.
series_exemplo = pd.Series({'Ana':20, 'João': 19, 'Maria': 21, 'Pedro': 22, 'Túlio': 20})
pd.DataFrame(series_exemplo)
| 0 | |
|---|---|
| Ana | 20 | 
| João | 19 | 
| Maria | 21 | 
| Pedro | 22 | 
| Túlio | 20 | 
Caso a Series possua um atributo name especificado, este será o nome da coluna do DataFrame.
series_exemplo_Idade = pd.Series({'Ana':20, 'João': 19, 'Maria': 21, 'Pedro': 22, 'Túlio': 20}, name="Idade")
pd.DataFrame(series_exemplo_Idade)
| Idade | |
|---|---|
| Ana | 20 | 
| João | 19 | 
| Maria | 21 | 
| Pedro | 22 | 
| Túlio | 20 | 
DataFrame a partir de lista de Series do pandas¶
Neste caso, a entrada dos dados da lista no DataFrame será feita por linha.
pd.DataFrame([serie_Peso, serie_Altura, serie_Idade])
| Ana | João | Maria | Pedro | Túlio | |
|---|---|---|---|---|---|
| Peso | 55.0 | 80.0 | 62.0 | 67.0 | 73.0 | 
| Altura | 162.0 | 178.0 | 162.0 | 165.0 | 171.0 | 
| Idade | 20.0 | 19.0 | 21.0 | 22.0 | NaN | 
Podemos corrigir a orientação usando o método transpose.
pd.DataFrame([serie_Peso, serie_Altura, serie_Idade]).transpose()
| Peso | Altura | Idade | |
|---|---|---|---|
| Ana | 55.0 | 162.0 | 20.0 | 
| João | 80.0 | 178.0 | 19.0 | 
| Maria | 62.0 | 162.0 | 21.0 | 
| Pedro | 67.0 | 165.0 | 22.0 | 
| Túlio | 73.0 | 171.0 | NaN | 
DataFrame a partir de arquivos¶
Para criar um DataFrame a partir de um arquivo, precisamos de funções do tipo pd.read_FORMATO, onde FORMATO indica o formato a ser importado sob o pressuposto de que a biblioteca pandas foi devidamente importada com pd.
Os formatos mais comuns são:
csv (comma-separated values),
xls ou xlsx (formatos do Microsoft Excel),
hdf5 (comumente utilizado em big data),
json (comumente utilizado em páginas da internet).
As funções para leitura correspondentes são:
pd.read_csv,pd.read_excel,pd.read_hdf,pd.read_json,
respectivamente.
De todas elas, a função mais utilizada é read_csv. Ela possui vários argumentos. Vejamos os mais utilizados:
file_path_or_buffer: o endereço do arquivo a ser lido. Pode ser um endereço da internet.sep: o separador entre as entradas de dados. O separador padrão é,.index_col: a coluna que deve ser usada para formar o index. O padrão éNone. Porém pode ser alterado para outro. Um separador comumente encontrado é o\t(TAB).names: nomes das colunas a serem usadas. O padrão éNone.header: número da linha que servirá como nome para as colunas. O padrão éinfer(ou seja, tenta deduzir automaticamente). Se os nomes das colunas forem passados através donames, entãoheaderserá automaticamente considerado comoNone.
Exemplo: considere o arquivo data/exemplo_data.csv contendo:
,coluna_1,coluna_2
2020-01-01,-0.4160923582996922,1.8103644347460834
2020-01-02,-0.1379696602473578,2.5785204825192785
2020-01-03,0.5758273450544708,0.06086648807755068
2020-01-04,-0.017367186564883633,1.2995865328684455
2020-01-05,1.3842792448510655,-0.3817320973859929
2020-01-06,0.5497056238566345,-1.308789022968975
2020-01-07,-0.2822962331437976,-1.6889791765925102
2020-01-08,-0.9897300598660013,-0.028120707936426497
2020-01-09,0.27558240737928663,-0.1776585993494299
2020-01-10,0.6851316082235455,0.5025348904591399
Para ler o arquivo acima basta fazer:
df_exemplo_0 = pd.read_csv('../database/exemplo_data.csv')
df_exemplo_0
| Unnamed: 0 | coluna_1 | coluna_2 | |
|---|---|---|---|
| 0 | 2020-01-01 | -0.416092 | 1.810364 | 
| 1 | 2020-01-02 | -0.137970 | 2.578520 | 
| 2 | 2020-01-03 | 0.575827 | 0.060866 | 
| 3 | 2020-01-04 | -0.017367 | 1.299587 | 
| 4 | 2020-01-05 | 1.384279 | -0.381732 | 
| 5 | 2020-01-06 | 0.549706 | -1.308789 | 
| 6 | 2020-01-07 | -0.282296 | -1.688979 | 
| 7 | 2020-01-08 | -0.989730 | -0.028121 | 
| 8 | 2020-01-09 | 0.275582 | -0.177659 | 
| 9 | 2020-01-10 | 0.685132 | 0.502535 | 
No exemplo anterior, as colunas receberam nomes corretamentes exceto pela primeira coluna que gostaríamos de considerar como index. Neste caso fazemos:
df_exemplo = pd.read_csv('../database/exemplo_data.csv', index_col=0)
df_exemplo
| coluna_1 | coluna_2 | |
|---|---|---|
| 2020-01-01 | -0.416092 | 1.810364 | 
| 2020-01-02 | -0.137970 | 2.578520 | 
| 2020-01-03 | 0.575827 | 0.060866 | 
| 2020-01-04 | -0.017367 | 1.299587 | 
| 2020-01-05 | 1.384279 | -0.381732 | 
| 2020-01-06 | 0.549706 | -1.308789 | 
| 2020-01-07 | -0.282296 | -1.688979 | 
| 2020-01-08 | -0.989730 | -0.028121 | 
| 2020-01-09 | 0.275582 | -0.177659 | 
| 2020-01-10 | 0.685132 | 0.502535 | 
O método head do DataFrame¶
O método head, sem argumento, permite que visualizemos as 5 primeiras linhas do DataFrame.
df_exemplo.head()
| coluna_1 | coluna_2 | |
|---|---|---|
| 2020-01-01 | -0.416092 | 1.810364 | 
| 2020-01-02 | -0.137970 | 2.578520 | 
| 2020-01-03 | 0.575827 | 0.060866 | 
| 2020-01-04 | -0.017367 | 1.299587 | 
| 2020-01-05 | 1.384279 | -0.381732 | 
Se for passado um argumento com valor n, as n primeiras linhas são impressas.
df_exemplo.head(2)
| coluna_1 | coluna_2 | |
|---|---|---|
| 2020-01-01 | -0.416092 | 1.810364 | 
| 2020-01-02 | -0.137970 | 2.578520 | 
df_exemplo.head(7)
| coluna_1 | coluna_2 | |
|---|---|---|
| 2020-01-01 | -0.416092 | 1.810364 | 
| 2020-01-02 | -0.137970 | 2.578520 | 
| 2020-01-03 | 0.575827 | 0.060866 | 
| 2020-01-04 | -0.017367 | 1.299587 | 
| 2020-01-05 | 1.384279 | -0.381732 | 
| 2020-01-06 | 0.549706 | -1.308789 | 
| 2020-01-07 | -0.282296 | -1.688979 | 
O método tail do DataFrame¶
O método tail, sem argumento, retorna as últimas 5 linhas do DataFrame.
df_exemplo.tail()
| coluna_1 | coluna_2 | |
|---|---|---|
| 2020-01-06 | 0.549706 | -1.308789 | 
| 2020-01-07 | -0.282296 | -1.688979 | 
| 2020-01-08 | -0.989730 | -0.028121 | 
| 2020-01-09 | 0.275582 | -0.177659 | 
| 2020-01-10 | 0.685132 | 0.502535 | 
Se for passado um argumento com valor n, as n últimas linhas são impressas.
df_exemplo.tail(2)
| coluna_1 | coluna_2 | |
|---|---|---|
| 2020-01-09 | 0.275582 | -0.177659 | 
| 2020-01-10 | 0.685132 | 0.502535 | 
df_exemplo.tail(7)
| coluna_1 | coluna_2 | |
|---|---|---|
| 2020-01-04 | -0.017367 | 1.299587 | 
| 2020-01-05 | 1.384279 | -0.381732 | 
| 2020-01-06 | 0.549706 | -1.308789 | 
| 2020-01-07 | -0.282296 | -1.688979 | 
| 2020-01-08 | -0.989730 | -0.028121 | 
| 2020-01-09 | 0.275582 | -0.177659 | 
| 2020-01-10 | 0.685132 | 0.502535 | 
Atributos de Series e DataFrames¶
Atributos comumente usados para Series e DataFrames são:
shape: fornece as dimensões do objeto em questão (Series ou DataFrame) em formato consistente com o atributoshapede um array do numpy.index: fornece o índice do objeto. No caso do DataFrame são os rótulos das linhas.columns: fornece as colunas (apenas disponível para DataFrames)
Exemplo:
df_exemplo.shape
(10, 2)
serie_1 = pd.Series([1,2,3,4,5])
serie_1.shape
(5,)
df_exemplo.index
Index(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04', '2020-01-05',
       '2020-01-06', '2020-01-07', '2020-01-08', '2020-01-09', '2020-01-10'],
      dtype='object')
serie_1.index
RangeIndex(start=0, stop=5, step=1)
df_exemplo.columns
Index(['coluna_1', 'coluna_2'], dtype='object')
Se quisermos obter os dados contidos nos index ou nas Series podemos utilizar a propriedade .array.
serie_1.index.array
<PandasArray>
[0, 1, 2, 3, 4]
Length: 5, dtype: int64
df_exemplo.columns.array
<PandasArray>
['coluna_1', 'coluna_2']
Length: 2, dtype: object
Se o interesse for obter os dados como um array do numpy, devemos utilizar o método .to_numpy().
Exemplo:
serie_1.index.to_numpy()
array([0, 1, 2, 3, 4])
df_exemplo.columns.to_numpy()
array(['coluna_1', 'coluna_2'], dtype=object)
O método .to_numpy() também está disponível em DataFrames:
df_exemplo.to_numpy()
array([[-0.41609236,  1.81036443],
       [-0.13796966,  2.57852048],
       [ 0.57582735,  0.06086649],
       [-0.01736719,  1.29958653],
       [ 1.38427924, -0.3817321 ],
       [ 0.54970562, -1.30878902],
       [-0.28229623, -1.68897918],
       [-0.98973006, -0.02812071],
       [ 0.27558241, -0.1776586 ],
       [ 0.68513161,  0.50253489]])
A função do numpy asarray() é compatível com index, columns e DataFrames do pandas:
np.asarray(df_exemplo.index)
array(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04',
       '2020-01-05', '2020-01-06', '2020-01-07', '2020-01-08',
       '2020-01-09', '2020-01-10'], dtype=object)
np.asarray(df_exemplo.columns)
array(['coluna_1', 'coluna_2'], dtype=object)
np.asarray(df_exemplo)
array([[-0.41609236,  1.81036443],
       [-0.13796966,  2.57852048],
       [ 0.57582735,  0.06086649],
       [-0.01736719,  1.29958653],
       [ 1.38427924, -0.3817321 ],
       [ 0.54970562, -1.30878902],
       [-0.28229623, -1.68897918],
       [-0.98973006, -0.02812071],
       [ 0.27558241, -0.1776586 ],
       [ 0.68513161,  0.50253489]])
Informações sobre as colunas de um DataFrame¶
Para obtermos uma breve descrição sobre as colunas de um DataFrame utilizamos o método info.
Exemplo:
df_exemplo.info()
<class 'pandas.core.frame.DataFrame'>
Index: 10 entries, 2020-01-01 to 2020-01-10
Data columns (total 2 columns):
 #   Column    Non-Null Count  Dtype  
---  ------    --------------  -----  
 0   coluna_1  10 non-null     float64
 1   coluna_2  10 non-null     float64
dtypes: float64(2)
memory usage: 240.0+ bytes
Criando arquivos a partir de DataFrames¶
Para criar arquivos a partir de DataFrames, basta utilizar os métodos do tipo pd.to_FORMATO, onde FORMATO indica o formato a ser exportado e supondo que a biblioteca pandas foi importada com pd.
Com relação aos tipos de arquivo anteriores, os métodos para exportação correspondentes são:
.to_csv(‘endereço_do_arquivo’),.to_excel(‘endereço_do_arquivo’),.to_hdf(‘endereço_do_arquivo’),.to_json(‘endereço_do_arquivo’),
onde endereço_do_arquivo é uma str que contém o endereço do arquivo a ser exportado.
Exemplo:
Para exportar para o arquivo exemplo_novo.csv, utilizaremos o método .to_csv ao DataFrame df_exemplo:
df_exemplo.to_csv('../database/exemplo_novo.csv')
Exemplo COVID-19 PB¶
Dados diários de COVID-19 do estado da Paraíba:
Fonte: https://superset.plataformatarget.com.br/superset/dashboard/microdados/
dados_covid_PB = pd.read_csv('https://superset.plataformatarget.com.br/superset/explore_json/?form_data=%7B%22slice_id%22%3A1550%7D&csv=true', 
                             sep=',', index_col=0)
dados_covid_PB.info()
<class 'pandas.core.frame.DataFrame'>
Index: 559 entries, 2021-09-26 to 2020-03-16
Data columns (total 7 columns):
 #   Column            Non-Null Count  Dtype  
---  ------            --------------  -----  
 0   casosAcumulados   559 non-null    int64  
 1   casosNovos        559 non-null    int64  
 2   descartados       559 non-null    int64  
 3   recuperados       559 non-null    int64  
 4   obitosAcumulados  559 non-null    int64  
 5   obitosNovos       558 non-null    float64
 6   Letalidade        559 non-null    float64
dtypes: float64(2), int64(5)
memory usage: 34.9+ KB
dados_covid_PB.head()
| casosAcumulados | casosNovos | descartados | recuperados | obitosAcumulados | obitosNovos | Letalidade | |
|---|---|---|---|---|---|---|---|
| data | |||||||
| 2021-09-26 | 441155 | 134 | 484336 | 333751 | 9294 | 2.0 | 0.0211 | 
| 2021-09-25 | 441021 | 165 | 484331 | 333441 | 9292 | 2.0 | 0.0211 | 
| 2021-09-24 | 440856 | 225 | 484301 | 332845 | 9290 | 3.0 | 0.0211 | 
| 2021-09-23 | 440631 | 203 | 484276 | 332540 | 9287 | 3.0 | 0.0211 | 
| 2021-09-22 | 440428 | 297 | 484265 | 331958 | 9284 | 6.0 | 0.0211 | 
dados_covid_PB.tail()
| casosAcumulados | casosNovos | descartados | recuperados | obitosAcumulados | obitosNovos | Letalidade | |
|---|---|---|---|---|---|---|---|
| data | |||||||
| 2020-03-20 | 0 | 0 | 0 | 0 | 0 | 0.0 | 0.0 | 
| 2020-03-19 | 0 | 0 | 0 | 0 | 0 | 0.0 | 0.0 | 
| 2020-03-18 | 0 | 0 | 0 | 0 | 0 | 0.0 | 0.0 | 
| 2020-03-17 | 0 | 0 | 0 | 0 | 0 | 0.0 | 0.0 | 
| 2020-03-16 | 0 | 0 | 0 | 0 | 0 | 0.0 | 0.0 | 
dados_covid_PB['estado'] = 'PB'
dados_covid_PB.head()
| casosAcumulados | casosNovos | descartados | recuperados | obitosAcumulados | obitosNovos | Letalidade | estado | |
|---|---|---|---|---|---|---|---|---|
| data | ||||||||
| 2021-09-26 | 441155 | 134 | 484336 | 333751 | 9294 | 2.0 | 0.0211 | PB | 
| 2021-09-25 | 441021 | 165 | 484331 | 333441 | 9292 | 2.0 | 0.0211 | PB | 
| 2021-09-24 | 440856 | 225 | 484301 | 332845 | 9290 | 3.0 | 0.0211 | PB | 
| 2021-09-23 | 440631 | 203 | 484276 | 332540 | 9287 | 3.0 | 0.0211 | PB | 
| 2021-09-22 | 440428 | 297 | 484265 | 331958 | 9284 | 6.0 | 0.0211 | PB | 
dados_covid_PB.to_csv('../database/dadoscovidpb.csv')
Índices dos valores máximos ou mínimos¶
Os métodos idxmin() e idxmax() retornam o index cuja entrada fornece o valor mínimo ou máximo da Series ou DataFrame. Se houver múltiplas ocorrências de mínimos ou máximos, o método retorna a primeira ocorrência.
Vamos recriar um DataFrame genérico.
serie_Idade = pd.Series({'Ana':20, 'João': 19, 'Maria': 21, 'Pedro': 22, 'Túlio': 20}, name="Idade")
serie_Peso = pd.Series({'Ana':55, 'João': 80, 'Maria': 62, 'Pedro': 67, 'Túlio': 73}, name="Peso")
serie_Altura = pd.Series({'Ana':162, 'João': 178, 'Maria': 162, 'Pedro': 165, 'Túlio': 171}, name="Altura")
dicionario_series_exemplo = {'Idade': serie_Idade, 'Peso': serie_Peso, 'Altura': serie_Altura}
df_dict_series = pd.DataFrame(dicionario_series_exemplo)
df_dict_series
| Idade | Peso | Altura | |
|---|---|---|---|
| Ana | 20 | 55 | 162 | 
| João | 19 | 80 | 178 | 
| Maria | 21 | 62 | 162 | 
| Pedro | 22 | 67 | 165 | 
| Túlio | 20 | 73 | 171 | 
Assim, podemos localizar quem possui menores idade, peso e altura.
df_dict_series.idxmin()
Idade     João
Peso       Ana
Altura     Ana
dtype: object
De igual forma, localizamos quem possui maiores idade, peso e altura.
df_dict_series.idxmax()
Idade     Pedro
Peso       João
Altura     João
dtype: object
Exemplo: Aplicaremos as funções idxmin() e idxmax() aos dados do arquivo data/exemplo_data.csv para localizar entradas de interesse.
df_exemplo = pd.read_csv('../database/exemplo_data.csv', index_col=0); df_exemplo
| coluna_1 | coluna_2 | |
|---|---|---|
| 2020-01-01 | -0.416092 | 1.810364 | 
| 2020-01-02 | -0.137970 | 2.578520 | 
| 2020-01-03 | 0.575827 | 0.060866 | 
| 2020-01-04 | -0.017367 | 1.299587 | 
| 2020-01-05 | 1.384279 | -0.381732 | 
| 2020-01-06 | 0.549706 | -1.308789 | 
| 2020-01-07 | -0.282296 | -1.688979 | 
| 2020-01-08 | -0.989730 | -0.028121 | 
| 2020-01-09 | 0.275582 | -0.177659 | 
| 2020-01-10 | 0.685132 | 0.502535 | 
df_exemplo = pd.DataFrame(df_exemplo, columns=['coluna_1','coluna_2','coluna_3'])
Inserimos uma terceira coluna com dados fictícios.
df_exemplo['coluna_3'] = pd.Series([1,2,3,4,5,6,7,8,np.nan,np.nan],index=df_exemplo.index)
df_exemplo
| coluna_1 | coluna_2 | coluna_3 | |
|---|---|---|---|
| 2020-01-01 | -0.416092 | 1.810364 | 1.0 | 
| 2020-01-02 | -0.137970 | 2.578520 | 2.0 | 
| 2020-01-03 | 0.575827 | 0.060866 | 3.0 | 
| 2020-01-04 | -0.017367 | 1.299587 | 4.0 | 
| 2020-01-05 | 1.384279 | -0.381732 | 5.0 | 
| 2020-01-06 | 0.549706 | -1.308789 | 6.0 | 
| 2020-01-07 | -0.282296 | -1.688979 | 7.0 | 
| 2020-01-08 | -0.989730 | -0.028121 | 8.0 | 
| 2020-01-09 | 0.275582 | -0.177659 | NaN | 
| 2020-01-10 | 0.685132 | 0.502535 | NaN | 
Os index correspondentes aos menores e maiores valores são datas, evidentemente.
df_exemplo.idxmin()
coluna_1    2020-01-08
coluna_2    2020-01-07
coluna_3    2020-01-01
dtype: object
df_exemplo.idxmax()
coluna_1    2020-01-05
coluna_2    2020-01-02
coluna_3    2020-01-08
dtype: object
Reindexação de DataFrames¶
No pandas, o método reindex
reordena o DataFrame de acordo com o conjunto de rótulos inserido como argumento;
insere valores faltantes caso um rótulo do novo index não tenha valor atribuído no conjunto de dados;
remove valores correspondentes a rótulos que não estão presentes no novo index.
Exemplos:
df_dict_series.reindex(index=['Victor', 'Túlio', 'Pedro', 'João'], columns=['Altura','Peso','IMC'])
| Altura | Peso | IMC | |
|---|---|---|---|
| Victor | NaN | NaN | NaN | 
| Túlio | 171.0 | 73.0 | NaN | 
| Pedro | 165.0 | 67.0 | NaN | 
| João | 178.0 | 80.0 | NaN | 
Remoção de linhas ou colunas de um DataFrame¶
Para remover linhas ou colunas de um DataFrame do pandas podemos utilizar o método drop. O argumento axis identifica o eixo de remoção: axis=0, que é o padrão, indica a remoção de uma ou mais linhas; axis=1 indica a remoção de uma ou mais colunas.
Nos exemplos que segue, note que novos DataFrames são obtidos a partir de df_dict_series sem que este seja sobrescrito.
df_dict_series.drop('Túlio') # axis=0 implícito 
| Idade | Peso | Altura | |
|---|---|---|---|
| Ana | 20 | 55 | 162 | 
| João | 19 | 80 | 178 | 
| Maria | 21 | 62 | 162 | 
| Pedro | 22 | 67 | 165 | 
df_dict_series.drop(['Ana','Maria'], axis=0)
| Idade | Peso | Altura | |
|---|---|---|---|
| João | 19 | 80 | 178 | 
| Pedro | 22 | 67 | 165 | 
| Túlio | 20 | 73 | 171 | 
df_dict_series.drop(['Idade'], axis=1)
| Peso | Altura | |
|---|---|---|
| Ana | 55 | 162 | 
| João | 80 | 178 | 
| Maria | 62 | 162 | 
| Pedro | 67 | 165 | 
| Túlio | 73 | 171 | 
Renomeando index e columns¶
O método rename retorna uma cópia na qual o index (no caso de Series e DataFrames) e columns (no caso de DataFrames) foram renomeados. O método aceita como entrada um dicionário, uma Series do pandas ou uma função.
Exemplo:
serie_exemplo = pd.Series([1,2,3], index=['a','b','c'])
serie_exemplo
a    1
b    2
c    3
dtype: int64
serie_exemplo.rename({'a':'abacaxi', 'b':'banana', 'c': 'cebola'})
abacaxi    1
banana     2
cebola     3
dtype: int64
Exemplo:
df_dict_series
| Idade | Peso | Altura | |
|---|---|---|---|
| Ana | 20 | 55 | 162 | 
| João | 19 | 80 | 178 | 
| Maria | 21 | 62 | 162 | 
| Pedro | 22 | 67 | 165 | 
| Túlio | 20 | 73 | 171 | 
df_dict_series.rename(index = {'Ana':'a', 'João':'j', 'Maria':'m', 'Pedro':'p','Túlio':'t'},
                     columns = {'Idade':'I', 'Peso':'P','Altura':'A'})
| I | P | A | |
|---|---|---|---|
| a | 20 | 55 | 162 | 
| j | 19 | 80 | 178 | 
| m | 21 | 62 | 162 | 
| p | 22 | 67 | 165 | 
| t | 20 | 73 | 171 | 
No próximo exemplo, usamos uma Series para renomear os rótulos.
indice_novo = pd.Series({'Ana':'a', 'João':'j', 'Maria':'m', 'Pedro':'p','Túlio':'t'})
df_dict_series.rename(index = indice_novo)
| Idade | Peso | Altura | |
|---|---|---|---|
| a | 20 | 55 | 162 | 
| j | 19 | 80 | 178 | 
| m | 21 | 62 | 162 | 
| p | 22 | 67 | 165 | 
| t | 20 | 73 | 171 | 
Neste exemplo, usamos a função str.upper (altera a str para “todas maiúsculas”) para renomear colunas.
df_dict_series.rename(columns=str.upper)
| IDADE | PESO | ALTURA | |
|---|---|---|---|
| Ana | 20 | 55 | 162 | 
| João | 19 | 80 | 178 | 
| Maria | 21 | 62 | 162 | 
| Pedro | 22 | 67 | 165 | 
| Túlio | 20 | 73 | 171 | 
Ordenação de Series e DataFrames¶
É possível ordenar ambos pelos rótulos do index (para tanto é necessário que eles sejam ordenáveis) ou por valores nas colunas.
O método sort_index ordena a Series ou o DataFrame pelo index. O método sort_values ordena a Series ou o DataFrame pelos valores (escolhendo uma ou mais colunas no caso de DataFrames). No caso do DataFrame, o argumento by é necessário para indicar qual(is) coluna(s) será(ão) utilizada(s) como base para a ordenação.
Exemplos:
serie_desordenada = pd.Series({'Maria': 21, 'Pedro': 22, 'Túlio': 20, 'João': 19, 'Ana':20}); 
serie_desordenada
Maria    21
Pedro    22
Túlio    20
João     19
Ana      20
dtype: int64
serie_desordenada.sort_index() # ordenação alfabética
Ana      20
João     19
Maria    21
Pedro    22
Túlio    20
dtype: int64
Mais exemplos:
df_desordenado = df_dict_series.reindex(index=['Pedro','Maria','Ana','Túlio','João'])
df_desordenado
| Idade | Peso | Altura | |
|---|---|---|---|
| Pedro | 22 | 67 | 165 | 
| Maria | 21 | 62 | 162 | 
| Ana | 20 | 55 | 162 | 
| Túlio | 20 | 73 | 171 | 
| João | 19 | 80 | 178 | 
df_desordenado.sort_index()
| Idade | Peso | Altura | |
|---|---|---|---|
| Ana | 20 | 55 | 162 | 
| João | 19 | 80 | 178 | 
| Maria | 21 | 62 | 162 | 
| Pedro | 22 | 67 | 165 | 
| Túlio | 20 | 73 | 171 | 
Mais exemplos:
serie_desordenada.sort_values()
João     19
Túlio    20
Ana      20
Maria    21
Pedro    22
dtype: int64
df_desordenado.sort_values(by=['Altura']) # ordena por 'Altura'
| Idade | Peso | Altura | |
|---|---|---|---|
| Maria | 21 | 62 | 162 | 
| Ana | 20 | 55 | 162 | 
| Pedro | 22 | 67 | 165 | 
| Túlio | 20 | 73 | 171 | 
| João | 19 | 80 | 178 | 
No caso de “empate”, podemos utilizar outra coluna para desempatar.
df_desordenado.sort_values(by=['Altura','Peso']) # usa a coluna 'Peso' para desempatar
| Idade | Peso | Altura | |
|---|---|---|---|
| Ana | 20 | 55 | 162 | 
| Maria | 21 | 62 | 162 | 
| Pedro | 22 | 67 | 165 | 
| Túlio | 20 | 73 | 171 | 
| João | 19 | 80 | 178 | 
Os métodos sort_index e sort_values admitem o argumento opcional ascending, que permite inverter a ordenação caso tenha valor False.
df_desordenado.sort_index(ascending=False)
| Idade | Peso | Altura | |
|---|---|---|---|
| Túlio | 20 | 73 | 171 | 
| Pedro | 22 | 67 | 165 | 
| Maria | 21 | 62 | 162 | 
| João | 19 | 80 | 178 | 
| Ana | 20 | 55 | 162 | 
df_desordenado.sort_values(by=['Idade'], ascending=False)
| Idade | Peso | Altura | |
|---|---|---|---|
| Pedro | 22 | 67 | 165 | 
| Maria | 21 | 62 | 162 | 
| Ana | 20 | 55 | 162 | 
| Túlio | 20 | 73 | 171 | 
| João | 19 | 80 | 178 | 
Comparação de Series e DataFrames¶
Series e DataFrames possuem os seguintes métodos de comparação lógica:
eq(igual);ne(diferente);lt(menor do que);gt(maior do que);le(menor ou igual a);ge(maior ou igual a)
que permitem a utilização dos operadores binários ==, !=, <, >, <= e >=, respectivamente. As comparações são realizadas em cada entrada da Series ou do DataFrame.
Observação: Para que esses métodos sejam aplicados, todos os objetos presentes nas colunas do DataFrame devem ser de mesma natureza. Por exemplo, se um DataFrame possui algumas colunas numéricas e outras com strings, ao realizar uma comparação do tipo > 1, um erro ocorrerá, pois o pandas tentará comparar objetos do tipo int com objetos do tipo str, assim gerando uma incompatibilidade.
Exemplos:
serie_exemplo
a    1
b    2
c    3
dtype: int64
serie_exemplo == 2
a    False
b     True
c    False
dtype: bool
De outra forma:
serie_exemplo.eq(2)
a    False
b     True
c    False
dtype: bool
serie_exemplo > 1
a    False
b     True
c     True
dtype: bool
Ou, na forma funcional:
serie_exemplo.gt(1)
a    False
b     True
c     True
dtype: bool
df_exemplo > 1
| coluna_1 | coluna_2 | coluna_3 | |
|---|---|---|---|
| 2020-01-01 | False | True | False | 
| 2020-01-02 | False | True | True | 
| 2020-01-03 | False | False | True | 
| 2020-01-04 | False | True | True | 
| 2020-01-05 | True | False | True | 
| 2020-01-06 | False | False | True | 
| 2020-01-07 | False | False | True | 
| 2020-01-08 | False | False | True | 
| 2020-01-09 | False | False | False | 
| 2020-01-10 | False | False | False | 
Importante: Ao comparar np.nan, o resultado tipicamente é falso:
np.nan == np.nan
False
np.nan > np.nan
False
np.nan >= np.nan
False
Só é verdadeiro para indicar que é diferente:
np.nan != np.nan
True
Neste sentido, podemos ter tabelas iguais sem que a comparação usual funcione:
# 'copy', como o nome sugere, gera uma cópia do DataFrame
df_exemplo_2 = df_exemplo.copy() 
(df_exemplo == df_exemplo_2)
| coluna_1 | coluna_2 | coluna_3 | |
|---|---|---|---|
| 2020-01-01 | True | True | True | 
| 2020-01-02 | True | True | True | 
| 2020-01-03 | True | True | True | 
| 2020-01-04 | True | True | True | 
| 2020-01-05 | True | True | True | 
| 2020-01-06 | True | True | True | 
| 2020-01-07 | True | True | True | 
| 2020-01-08 | True | True | True | 
| 2020-01-09 | True | True | False | 
| 2020-01-10 | True | True | False | 
O motivo de haver entradas como False ainda que df_exemplo_2 seja uma cópia exata de df_exemplo é a presença do np.nan. Neste caso, devemos utilizar o método equals para realizar a comparação.
df_exemplo.equals(df_exemplo_2)
True
Os métodos any, all e a propriedade empty¶
O método any é aplicado a entradas booleanas (verdadeiras ou falsas) e retorna verdadeiro se existir alguma entrada verdadeira, ou falso, se todas forem falsas. O método all é aplicado a entradas booleanas e retorna verdadeiro se todas as entradas forem verdadeiras, ou falso,  se houver pelo menos uma entrada falsa. A propriedade empty retorna verdadeiro se a Series ou o DataFrame estiver vazio, ou falso caso contrário.
Exemplos:
serie_exemplo
a    1
b    2
c    3
dtype: int64
serie_exemplo_2 = serie_exemplo-2; 
serie_exemplo_2
a   -1
b    0
c    1
dtype: int64
(serie_exemplo_2 > 0).any()
True
(serie_exemplo > 1).all()
False
Este exemplo reproduz um valor False único.
(df_exemplo == df_exemplo_2).all().all()
False
serie_exemplo.empty
False
Mais exemplos:
(df_exemplo == df_exemplo_2).any()
coluna_1    True
coluna_2    True
coluna_3    True
dtype: bool
df_exemplo.empty
False
df_vazio = pd.DataFrame()
df_vazio.empty
True
Seleção de colunas de um DataFrame¶
Para selecionar colunas de um DataFrame, basta aplicar colchetes a uma lista contendo os nomes das colunas de interesse.
No exemplo abaixo, temos um DataFrame contendo as colunas 'Idade', 'Peso' e 'Altura'. Selecionaremos 'Peso' e 'Altura', apenas.
df_dict_series[['Peso','Altura']]
| Peso | Altura | |
|---|---|---|
| Ana | 55 | 162 | 
| João | 80 | 178 | 
| Maria | 62 | 162 | 
| Pedro | 67 | 165 | 
| Túlio | 73 | 171 | 
Se quisermos selecionar apenas uma coluna, não há necessidade de inserir uma lista. Basta utilizar o nome da coluna:
df_dict_series['Peso']
Ana      55
João     80
Maria    62
Pedro    67
Túlio    73
Name: Peso, dtype: int64
Para remover colunas, podemos utilizar o método drop.
df_dict_series.drop(['Peso','Altura'], axis=1)
| Idade | |
|---|---|
| Ana | 20 | 
| João | 19 | 
| Maria | 21 | 
| Pedro | 22 | 
| Túlio | 20 | 
Criação de novas colunas a partir de colunas existentes¶
Um método eficiente para criar novas colunas a partir de colunas já existentes é eval. Neste método, podemos utilizar como argumento uma string contendo uma expressão matemática envolvendo nomes de colunas do DataFrame.
Como exemplo, vamos ver como calcular o IMC no DataFrame anterior:
df_dict_series.eval('Peso/(Altura/100)**2')
Ana      20.957171
João     25.249337
Maria    23.624447
Pedro    24.609734
Túlio    24.964946
dtype: float64
Se quisermos obter um DataFrame contendo o IMC como uma nova coluna, podemos utilizar o método assign (sem modificar o DataFrame original):
df_dict_series.assign(IMC=round(df_dict_series.eval('Peso/(Altura/100)**2'),2))
| Idade | Peso | Altura | IMC | |
|---|---|---|---|---|
| Ana | 20 | 55 | 162 | 20.96 | 
| João | 19 | 80 | 178 | 25.25 | 
| Maria | 21 | 62 | 162 | 23.62 | 
| Pedro | 22 | 67 | 165 | 24.61 | 
| Túlio | 20 | 73 | 171 | 24.96 | 
df_dict_series # não modificado
| Idade | Peso | Altura | |
|---|---|---|---|
| Ana | 20 | 55 | 162 | 
| João | 19 | 80 | 178 | 
| Maria | 21 | 62 | 162 | 
| Pedro | 22 | 67 | 165 | 
| Túlio | 20 | 73 | 171 | 
Se quisermos modificar o DataFrame para incluir a coluna IMC fazemos:
df_dict_series['IMC']=round(df_dict_series.eval('Peso/(Altura/100)**2'),2)
df_dict_series # modificado "in-place"
| Idade | Peso | Altura | IMC | |
|---|---|---|---|---|
| Ana | 20 | 55 | 162 | 20.96 | 
| João | 19 | 80 | 178 | 25.25 | 
| Maria | 21 | 62 | 162 | 23.62 | 
| Pedro | 22 | 67 | 165 | 24.61 | 
| Túlio | 20 | 73 | 171 | 24.96 | 
Seleção de linhas de um DataFrame¶
Podemos selecionar linhas de um DataFrame de diversas formas diferentes. Veremos agora algumas dessas formas.
Diferentemente da forma de selecionar colunas, para selecionar diretamente linhas de um DataFrame devemos utilizar o método loc (fornecendo o index, isto é, o rótulo da linha) ou o iloc (fornecendo a posição da linha):
Trabalharemos a seguir com um banco de dados atualizado sobre a COVID-19. Para tanto, importaremos o módulo datetime que nos auxiliará com datas.
import datetime
dados_covid_PB = pd.read_csv('https://superset.plataformatarget.com.br/superset/explore_json/?form_data=%7B%22slice_id%22%3A1550%7D&csv=true', 
                             sep=',', index_col=0)
# busca o banco na data D-1, visto que a atualização
# ocorre em D
ontem = (datetime.date.today() - datetime.timedelta(days=1)).strftime('%Y-%m-%d') 
dados_covid_PB.head(1)
| casosAcumulados | casosNovos | descartados | recuperados | obitosAcumulados | obitosNovos | Letalidade | |
|---|---|---|---|---|---|---|---|
| data | |||||||
| 2021-09-26 | 441155 | 134 | 484336 | 333751 | 9294 | 2.0 | 0.0211 | 
Podemos ver as informações de um único dia como argumento. Para tanto, excluímos a coluna 'Letalidade' (valor não inteiro) e convertemos o restante para valores inteiros:
dados_covid_PB.loc[ontem].drop('Letalidade').astype('int')
casosAcumulados     441155
casosNovos             134
descartados         484336
recuperados         333751
obitosAcumulados      9294
obitosNovos              2
Name: 2021-09-26, dtype: int64
Podemos selecionar um intervalo de datas como argumento (excluindo letalidade):
dados_covid_PB.index = pd.to_datetime(dados_covid_PB.index) # Convertendo o index de string para data
dados_covid_PB.loc[pd.date_range('2021-02-01',periods=5,freq="D")].drop('Letalidade',axis=1) 
                #função pd.date_range é muito útil para criar índices a partir de datas.
| casosAcumulados | casosNovos | descartados | recuperados | obitosAcumulados | obitosNovos | |
|---|---|---|---|---|---|---|
| 2021-02-01 | 192598 | 1014 | 234215 | 149235 | 4068 | 12.0 | 
| 2021-02-02 | 193465 | 867 | 234366 | 149242 | 4082 | 14.0 | 
| 2021-02-03 | 194519 | 1054 | 234902 | 149248 | 4096 | 14.0 | 
| 2021-02-04 | 195482 | 963 | 235319 | 149792 | 4110 | 14.0 | 
| 2021-02-05 | 196542 | 1060 | 236216 | 150169 | 4123 | 13.0 | 
Podemos colocar uma lista como argumento:
dados_covid_PB.loc[pd.to_datetime(['2021-01-01','2021-02-01'])]
| casosAcumulados | casosNovos | descartados | recuperados | obitosAcumulados | obitosNovos | Letalidade | |
|---|---|---|---|---|---|---|---|
| 2021-01-01 | 167062 | 578 | 219890 | 127388 | 3680 | 8.0 | 0.0220 | 
| 2021-02-01 | 192598 | 1014 | 234215 | 149235 | 4068 | 12.0 | 0.0211 | 
Vamos agora examinar os dados da posição 100 (novamente excluindo a coluna letalidade e convertendo para inteiro):
dados_covid_PB.iloc[100].drop('Letalidade').astype('int')
casosAcumulados     371133
casosNovos            2555
descartados         328941
recuperados         243203
obitosAcumulados      8316
obitosNovos             47
Name: 2021-06-18 00:00:00, dtype: int64
Podemos colocar um intervalo como argumento:
dados_covid_PB.iloc[50:55].drop('Letalidade', axis=1).astype('int') 
| casosAcumulados | casosNovos | descartados | recuperados | obitosAcumulados | obitosNovos | |
|---|---|---|---|---|---|---|
| data | ||||||
| 2021-08-07 | 424983 | 406 | 456236 | 298889 | 9049 | 12 | 
| 2021-08-06 | 424577 | 423 | 455493 | 298554 | 9037 | 14 | 
| 2021-08-05 | 424154 | 570 | 454357 | 297945 | 9023 | 5 | 
| 2021-08-04 | 423584 | 872 | 453146 | 297222 | 9018 | 7 | 
| 2021-08-03 | 422712 | 37 | 451358 | 296180 | 9011 | 8 | 
Seleção de colunas com loc e iloc¶
Podemos selecionar colunas utilizando os métodos loc e iloc utilizando um argumento adicional.
dados_covid_PB.loc[:,['casosNovos','obitosNovos']]
| casosNovos | obitosNovos | |
|---|---|---|
| data | ||
| 2021-09-26 | 134 | 2.0 | 
| 2021-09-25 | 165 | 2.0 | 
| 2021-09-24 | 225 | 3.0 | 
| 2021-09-23 | 203 | 3.0 | 
| 2021-09-22 | 297 | 6.0 | 
| ... | ... | ... | 
| 2020-03-20 | 0 | 0.0 | 
| 2020-03-19 | 0 | 0.0 | 
| 2020-03-18 | 0 | 0.0 | 
| 2020-03-17 | 0 | 0.0 | 
| 2020-03-16 | 0 | 0.0 | 
559 rows × 2 columns
dados_covid_PB.iloc[:,4:6] # fatiamento na coluna
| obitosAcumulados | obitosNovos | |
|---|---|---|
| data | ||
| 2021-09-26 | 9294 | 2.0 | 
| 2021-09-25 | 9292 | 2.0 | 
| 2021-09-24 | 9290 | 3.0 | 
| 2021-09-23 | 9287 | 3.0 | 
| 2021-09-22 | 9284 | 6.0 | 
| ... | ... | ... | 
| 2020-03-20 | 0 | 0.0 | 
| 2020-03-19 | 0 | 0.0 | 
| 2020-03-18 | 0 | 0.0 | 
| 2020-03-17 | 0 | 0.0 | 
| 2020-03-16 | 0 | 0.0 | 
559 rows × 2 columns
Seleção de linhas e colunas específicas com loc e iloc¶
Usando o mesmo princípio de fatiamento aplicado a arrays do numpy, podemos selecionar linhas e colunas em um intervalo específico de forma a obter uma subtabela.
dados_covid_PB.iloc[95:100,4:6]
| obitosAcumulados | obitosNovos | |
|---|---|---|
| data | ||
| 2021-06-23 | 8453 | 20.0 | 
| 2021-06-22 | 8433 | 22.0 | 
| 2021-06-21 | 8411 | 30.0 | 
| 2021-06-20 | 8381 | 33.0 | 
| 2021-06-19 | 8348 | 32.0 | 
Neste exemplo um pouco mais complexo, buscamos casos novos e óbitos novos em um período específico e ordenamos a tabela da data mais recente para a mais antiga.
dados_covid_PB.loc[pd.date_range('2020-04-06','2020-04-10'),['casosNovos','obitosNovos']].sort_index(ascending=False)
| casosNovos | obitosNovos | |
|---|---|---|
| 2020-04-10 | 6 | 0.0 | 
| 2020-04-09 | 24 | 4.0 | 
| 2020-04-08 | 14 | 3.0 | 
| 2020-04-07 | 5 | 0.0 | 
| 2020-04-06 | 1 | 0.0 | 
Suponha que o peso de Ana foi medido corretamente, mas registrado de maneira errônea no DataFrame df_dict_series como 55.
df_dict_series
| Idade | Peso | Altura | IMC | |
|---|---|---|---|---|
| Ana | 20 | 55 | 162 | 20.96 | 
| João | 19 | 80 | 178 | 25.25 | 
| Maria | 21 | 62 | 162 | 23.62 | 
| Pedro | 22 | 67 | 165 | 24.61 | 
| Túlio | 20 | 73 | 171 | 24.96 | 
Supondo que, na realidade, o valor é 65, alteramos a entrada específica com um simples loc. Em seguida, atualizamos a tabela.
df_dict_series.loc['Ana','Peso'] = 65
df_dict_series = df_dict_series.assign(IMC=round(df_dict_series.eval('Peso/(Altura/100)**2'),2)) # O IMC mudou
df_dict_series
| Idade | Peso | Altura | IMC | |
|---|---|---|---|---|
| Ana | 20 | 65 | 162 | 24.77 | 
| João | 19 | 80 | 178 | 25.25 | 
| Maria | 21 | 62 | 162 | 23.62 | 
| Pedro | 22 | 67 | 165 | 24.61 | 
| Túlio | 20 | 73 | 171 | 24.96 | 
Seleção de linhas através de critérios lógicos ou funções¶
Vamos selecionar quais os dias em que houve mais de 40 mortes registradas:
dados_covid_PB.loc[dados_covid_PB['obitosNovos']>40]
| casosAcumulados | casosNovos | descartados | recuperados | obitosAcumulados | obitosNovos | Letalidade | |
|---|---|---|---|---|---|---|---|
| data | |||||||
| 2021-06-18 | 371133 | 2555 | 328941 | 243203 | 8316 | 47.0 | 0.0224 | 
| 2021-06-11 | 354715 | 2451 | 322301 | 235778 | 8058 | 55.0 | 0.0227 | 
| 2021-06-10 | 352264 | 3911 | 231258 | 235329 | 8003 | 46.0 | 0.0227 | 
| 2021-04-27 | 289319 | 1037 | 290111 | 204340 | 6722 | 46.0 | 0.0232 | 
| 2021-04-19 | 280967 | 904 | 286168 | 194644 | 6487 | 43.0 | 0.0231 | 
| 2021-04-14 | 275301 | 1218 | 282121 | 193451 | 6316 | 42.0 | 0.0229 | 
| 2021-04-12 | 272811 | 1486 | 279801 | 193188 | 6234 | 58.0 | 0.0229 | 
| 2021-04-07 | 267008 | 1551 | 274623 | 189753 | 6050 | 49.0 | 0.0227 | 
| 2021-04-06 | 265457 | 817 | 273026 | 186879 | 6001 | 52.0 | 0.0226 | 
| 2021-04-05 | 264640 | 1059 | 272719 | 186670 | 5949 | 43.0 | 0.0225 | 
| 2021-04-03 | 262500 | 789 | 272207 | 186334 | 5866 | 46.0 | 0.0223 | 
| 2021-04-01 | 260484 | 1311 | 271069 | 186084 | 5791 | 47.0 | 0.0222 | 
| 2021-03-31 | 259173 | 1553 | 270560 | 183668 | 5744 | 73.0 | 0.0222 | 
| 2021-03-30 | 257620 | 1150 | 269399 | 183369 | 5671 | 70.0 | 0.0220 | 
| 2021-03-29 | 256470 | 968 | 268985 | 183028 | 5601 | 49.0 | 0.0218 | 
| 2021-03-28 | 255502 | 1203 | 268866 | 182873 | 5552 | 43.0 | 0.0217 | 
| 2021-03-27 | 254299 | 1410 | 268309 | 182680 | 5509 | 57.0 | 0.0217 | 
| 2021-03-26 | 252889 | 1611 | 266785 | 182404 | 5452 | 48.0 | 0.0216 | 
| 2021-03-25 | 251278 | 1672 | 265533 | 180125 | 5404 | 50.0 | 0.0215 | 
| 2021-03-24 | 249606 | 1154 | 264150 | 177812 | 5354 | 41.0 | 0.0214 | 
| 2021-03-23 | 248452 | 1140 | 264146 | 177591 | 5313 | 41.0 | 0.0214 | 
| 2021-03-20 | 245564 | 1300 | 264128 | 174980 | 5212 | 45.0 | 0.0212 | 
| 2021-03-19 | 244264 | 1269 | 264122 | 174769 | 5167 | 44.0 | 0.0212 | 
| 2021-03-18 | 242995 | 1403 | 258188 | 172789 | 5123 | 43.0 | 0.0211 | 
| 2021-03-17 | 241592 | 1194 | 256574 | 172492 | 5080 | 44.0 | 0.0210 | 
| 2021-03-16 | 240398 | 804 | 255491 | 172218 | 5036 | 44.0 | 0.0209 | 
| 2021-03-15 | 239594 | 1025 | 255162 | 171911 | 4992 | 59.0 | 0.0208 | 
| 2021-03-10 | 232771 | 1365 | 251742 | 170510 | 4797 | 50.0 | 0.0206 | 
| 2021-03-04 | 225672 | 1385 | 245919 | 164712 | 4612 | 54.0 | 0.0204 | 
| 2020-07-21 | 68844 | 1164 | 78605 | 25028 | 1558 | 41.0 | 0.0226 | 
| 2020-07-15 | 63939 | 1477 | 74399 | 23695 | 1383 | 41.0 | 0.0216 | 
| 2020-07-02 | 49536 | 1361 | 48272 | 16349 | 1044 | 42.0 | 0.0211 | 
| 2020-06-30 | 46957 | 1900 | 43070 | 14930 | 977 | 46.0 | 0.0208 | 
Selecionando os dias com mais de 25 óbitos e mais de 1500 casos novos:
dados_covid_PB.loc[(dados_covid_PB.obitosNovos > 25) & (dados_covid_PB.casosNovos>1500)]
| casosAcumulados | casosNovos | descartados | recuperados | obitosAcumulados | obitosNovos | Letalidade | |
|---|---|---|---|---|---|---|---|
| data | |||||||
| 2021-07-02 | 398440 | 1536 | 332530 | 262757 | 8654 | 26.0 | 0.0217 | 
| 2021-06-24 | 385018 | 2391 | 332313 | 250519 | 8479 | 26.0 | 0.0220 | 
| 2021-06-21 | 378064 | 2114 | 330969 | 249135 | 8411 | 30.0 | 0.0222 | 
| 2021-06-20 | 375950 | 2178 | 330721 | 248667 | 8381 | 33.0 | 0.0223 | 
| 2021-06-19 | 373772 | 2639 | 329903 | 248304 | 8348 | 32.0 | 0.0223 | 
| 2021-06-18 | 371133 | 2555 | 328941 | 243203 | 8316 | 47.0 | 0.0224 | 
| 2021-06-17 | 368578 | 2457 | 327929 | 242820 | 8269 | 32.0 | 0.0224 | 
| 2021-06-16 | 366121 | 2328 | 326517 | 242184 | 8237 | 40.0 | 0.0225 | 
| 2021-06-15 | 363793 | 2358 | 325032 | 241749 | 8197 | 39.0 | 0.0225 | 
| 2021-06-14 | 361435 | 2575 | 324438 | 241293 | 8158 | 30.0 | 0.0226 | 
| 2021-06-13 | 358860 | 2034 | 324327 | 236555 | 8128 | 33.0 | 0.0226 | 
| 2021-06-12 | 356826 | 2111 | 323444 | 236186 | 8095 | 37.0 | 0.0227 | 
| 2021-06-11 | 354715 | 2451 | 322301 | 235778 | 8058 | 55.0 | 0.0227 | 
| 2021-06-10 | 352264 | 3911 | 231258 | 235329 | 8003 | 46.0 | 0.0227 | 
| 2021-06-06 | 344174 | 1982 | 319055 | 230002 | 7849 | 29.0 | 0.0228 | 
| 2021-06-05 | 342192 | 1992 | 318096 | 229790 | 7820 | 29.0 | 0.0229 | 
| 2021-06-04 | 340200 | 2421 | 317390 | 229489 | 7791 | 26.0 | 0.0229 | 
| 2021-06-03 | 337779 | 2660 | 316011 | 229062 | 7765 | 30.0 | 0.0230 | 
| 2021-06-02 | 335119 | 2403 | 314538 | 225278 | 7735 | 32.0 | 0.0231 | 
| 2021-06-01 | 332716 | 1751 | 314520 | 224912 | 7703 | 31.0 | 0.0232 | 
| 2021-05-29 | 328771 | 2429 | 312011 | 224255 | 7617 | 28.0 | 0.0232 | 
| 2021-05-28 | 326342 | 1917 | 311013 | 223896 | 7589 | 33.0 | 0.0233 | 
| 2021-05-27 | 324425 | 1887 | 310639 | 223537 | 7556 | 36.0 | 0.0233 | 
| 2021-05-26 | 322538 | 2262 | 309492 | 221134 | 7520 | 36.0 | 0.0233 | 
| 2021-05-25 | 320276 | 2015 | 308275 | 220621 | 7484 | 36.0 | 0.0234 | 
| 2021-04-07 | 267008 | 1551 | 274623 | 189753 | 6050 | 49.0 | 0.0227 | 
| 2021-03-31 | 259173 | 1553 | 270560 | 183668 | 5744 | 73.0 | 0.0222 | 
| 2021-03-26 | 252889 | 1611 | 266785 | 182404 | 5452 | 48.0 | 0.0216 | 
| 2021-03-25 | 251278 | 1672 | 265533 | 180125 | 5404 | 50.0 | 0.0215 | 
| 2021-03-13 | 237313 | 1694 | 254238 | 171130 | 4896 | 31.0 | 0.0206 | 
| 2020-08-04 | 85760 | 1549 | 106500 | 38554 | 1901 | 31.0 | 0.0222 | 
| 2020-07-31 | 82794 | 1686 | 96753 | 35971 | 1811 | 26.0 | 0.0219 | 
| 2020-07-23 | 73104 | 2132 | 84047 | 28566 | 1618 | 37.0 | 0.0221 | 
| 2020-07-10 | 59118 | 1504 | 69567 | 21481 | 1229 | 33.0 | 0.0208 | 
| 2020-07-08 | 56344 | 1542 | 67549 | 19999 | 1171 | 26.0 | 0.0208 | 
| 2020-07-07 | 54802 | 1651 | 64933 | 19373 | 1145 | 27.0 | 0.0209 | 
| 2020-06-30 | 46957 | 1900 | 43070 | 14930 | 977 | 46.0 | 0.0208 | 
| 2020-06-09 | 22452 | 1501 | 20650 | 4671 | 534 | 27.0 | 0.0238 | 
Obs.: Note que podemos utilizar o nome da coluna como um atributo.
Vamos inserir uma coluna sobrenome no df_dict_series:
df_dict_series['Sobrenome'] = ['Silva', 'PraDo', 'Sales', 'MachadO', 'Coutinho']
df_dict_series
| Idade | Peso | Altura | IMC | Sobrenome | |
|---|---|---|---|---|---|
| Ana | 20 | 65 | 162 | 24.77 | Silva | 
| João | 19 | 80 | 178 | 25.25 | PraDo | 
| Maria | 21 | 62 | 162 | 23.62 | Sales | 
| Pedro | 22 | 67 | 165 | 24.61 | MachadO | 
| Túlio | 20 | 73 | 171 | 24.96 | Coutinho | 
Vamos encontrar as linhas cujo sobrenome termina em “do”. Para tanto, note que a função abaixo retorna True se o final é “do” e False caso contrário.
def verifica_final_do(palavra):
    return palavra.lower()[-2:] == 'do'
Obs.: Note que convertemos tudo para minúsculo.
Agora vamos utilizar essa função para alcançar nosso objetivo:
# 'map' aplica a função lambda a cada elemento da *Series*
df_dict_series['Sobrenome'].map(lambda palavra: palavra.lower()[-2:]=='do') 
Ana      False
João      True
Maria    False
Pedro     True
Túlio    False
Name: Sobrenome, dtype: bool
# procurando no df inteiro
df_dict_series.loc[df_dict_series['Sobrenome'].map(lambda palavra: palavra.lower()[-2:]=='do')]
| Idade | Peso | Altura | IMC | Sobrenome | |
|---|---|---|---|---|---|
| João | 19 | 80 | 178 | 25.25 | PraDo | 
| Pedro | 22 | 67 | 165 | 24.61 | MachadO | 
Vamos selecionar as linhas do mês 2 (fevereiro) usando index.month:
dados_covid_PB.loc[dados_covid_PB.index.month==2].head()
| casosAcumulados | casosNovos | descartados | recuperados | obitosAcumulados | obitosNovos | Letalidade | |
|---|---|---|---|---|---|---|---|
| data | |||||||
| 2021-02-28 | 221115 | 1392 | 245686 | 158304 | 4496 | 25.0 | 0.0203 | 
| 2021-02-27 | 219723 | 1416 | 245121 | 158132 | 4471 | 20.0 | 0.0203 | 
| 2021-02-26 | 218307 | 1186 | 244356 | 157849 | 4451 | 18.0 | 0.0204 | 
| 2021-02-25 | 217121 | 1594 | 243890 | 157586 | 4433 | 14.0 | 0.0204 | 
| 2021-02-24 | 215527 | 1320 | 243253 | 157329 | 4419 | 15.0 | 0.0205 | 
Seleção de linhas com o método query¶
Similarmente ao método eval, ao utilizarmos query, podemos criar expressões lógicas a partir de nomes das colunas do DataFrame.
Assim, podemos reescrever o código
dados_covid_PB.loc[(dados_covid_PB.obitosNovos>25) & 
                   (dados_covid_PB.casosNovos>1500)]
como
dados_covid_PB.query('obitosNovos>25 and casosNovos>1500') # note que 'and' é usado em vez de '&'
| casosAcumulados | casosNovos | descartados | recuperados | obitosAcumulados | obitosNovos | Letalidade | |
|---|---|---|---|---|---|---|---|
| data | |||||||
| 2021-07-02 | 398440 | 1536 | 332530 | 262757 | 8654 | 26.0 | 0.0217 | 
| 2021-06-24 | 385018 | 2391 | 332313 | 250519 | 8479 | 26.0 | 0.0220 | 
| 2021-06-21 | 378064 | 2114 | 330969 | 249135 | 8411 | 30.0 | 0.0222 | 
| 2021-06-20 | 375950 | 2178 | 330721 | 248667 | 8381 | 33.0 | 0.0223 | 
| 2021-06-19 | 373772 | 2639 | 329903 | 248304 | 8348 | 32.0 | 0.0223 | 
| 2021-06-18 | 371133 | 2555 | 328941 | 243203 | 8316 | 47.0 | 0.0224 | 
| 2021-06-17 | 368578 | 2457 | 327929 | 242820 | 8269 | 32.0 | 0.0224 | 
| 2021-06-16 | 366121 | 2328 | 326517 | 242184 | 8237 | 40.0 | 0.0225 | 
| 2021-06-15 | 363793 | 2358 | 325032 | 241749 | 8197 | 39.0 | 0.0225 | 
| 2021-06-14 | 361435 | 2575 | 324438 | 241293 | 8158 | 30.0 | 0.0226 | 
| 2021-06-13 | 358860 | 2034 | 324327 | 236555 | 8128 | 33.0 | 0.0226 | 
| 2021-06-12 | 356826 | 2111 | 323444 | 236186 | 8095 | 37.0 | 0.0227 | 
| 2021-06-11 | 354715 | 2451 | 322301 | 235778 | 8058 | 55.0 | 0.0227 | 
| 2021-06-10 | 352264 | 3911 | 231258 | 235329 | 8003 | 46.0 | 0.0227 | 
| 2021-06-06 | 344174 | 1982 | 319055 | 230002 | 7849 | 29.0 | 0.0228 | 
| 2021-06-05 | 342192 | 1992 | 318096 | 229790 | 7820 | 29.0 | 0.0229 | 
| 2021-06-04 | 340200 | 2421 | 317390 | 229489 | 7791 | 26.0 | 0.0229 | 
| 2021-06-03 | 337779 | 2660 | 316011 | 229062 | 7765 | 30.0 | 0.0230 | 
| 2021-06-02 | 335119 | 2403 | 314538 | 225278 | 7735 | 32.0 | 0.0231 | 
| 2021-06-01 | 332716 | 1751 | 314520 | 224912 | 7703 | 31.0 | 0.0232 | 
| 2021-05-29 | 328771 | 2429 | 312011 | 224255 | 7617 | 28.0 | 0.0232 | 
| 2021-05-28 | 326342 | 1917 | 311013 | 223896 | 7589 | 33.0 | 0.0233 | 
| 2021-05-27 | 324425 | 1887 | 310639 | 223537 | 7556 | 36.0 | 0.0233 | 
| 2021-05-26 | 322538 | 2262 | 309492 | 221134 | 7520 | 36.0 | 0.0233 | 
| 2021-05-25 | 320276 | 2015 | 308275 | 220621 | 7484 | 36.0 | 0.0234 | 
| 2021-04-07 | 267008 | 1551 | 274623 | 189753 | 6050 | 49.0 | 0.0227 | 
| 2021-03-31 | 259173 | 1553 | 270560 | 183668 | 5744 | 73.0 | 0.0222 | 
| 2021-03-26 | 252889 | 1611 | 266785 | 182404 | 5452 | 48.0 | 0.0216 | 
| 2021-03-25 | 251278 | 1672 | 265533 | 180125 | 5404 | 50.0 | 0.0215 | 
| 2021-03-13 | 237313 | 1694 | 254238 | 171130 | 4896 | 31.0 | 0.0206 | 
| 2020-08-04 | 85760 | 1549 | 106500 | 38554 | 1901 | 31.0 | 0.0222 | 
| 2020-07-31 | 82794 | 1686 | 96753 | 35971 | 1811 | 26.0 | 0.0219 | 
| 2020-07-23 | 73104 | 2132 | 84047 | 28566 | 1618 | 37.0 | 0.0221 | 
| 2020-07-10 | 59118 | 1504 | 69567 | 21481 | 1229 | 33.0 | 0.0208 | 
| 2020-07-08 | 56344 | 1542 | 67549 | 19999 | 1171 | 26.0 | 0.0208 | 
| 2020-07-07 | 54802 | 1651 | 64933 | 19373 | 1145 | 27.0 | 0.0209 | 
| 2020-06-30 | 46957 | 1900 | 43070 | 14930 | 977 | 46.0 | 0.0208 | 
| 2020-06-09 | 22452 | 1501 | 20650 | 4671 | 534 | 27.0 | 0.0238 |