Nesta aula, vamos trabalhar com métodos aplicáveis à limpeza de dados com Pandas. Veremos os métodos para:
Renomear colunas
Formatar textos (minúsculo, maísculo, primeira letra em maiúscula)
Realizar substituições com o método .replace()
Tratar nulos - método .fillna()
Converter tipos de dados em um dataframe
Criar funções anônimas - função lambda e método .apply().
Esses tópicos são fundamentais em processos de ETL (Extract, Transform and Load) em projetos envolvendo dados. Ao longo desse módulos, vamos trabalhar com o conjunto de dados `` que trata de clientes da CifraOnline, um banco digital fictício com 1000 linhas.
import pandas as pdclientes_cifraonline = pd.read_csv('dados/clientes-banco-cifraonline/clientes_cifraonline.csv')clientes_cifraonline.head()
nome
idade
sexo
salario
cidade
status_emprego
nivel_educacional
score_credito
0
João
62
M
R$ 6728
São Paulo
Desempregado
Mestrado
793
1
Mariano
65
M
R$ 7000
Porto Alegre
Autônomo
Pós-graduação
626
2
Luiz
71
M
R$ 6545
Rio de Janeiro
Autônomo
Graduação
438
3
Paula
18
F
R$ 3896
Salvador
Empregado
Ensino Médio
831
4
Carlo
21
M
R$ 12383
Salvador
Autônomo
Graduação
384
Antes de inicar os tópicos, é importante notarmos que temos, dentre outras particularidades:
Dados numéricos configurados como texto (coluna salario)
Nomes despadronizados quanto à formatação (coluna nome).
Para renomear colunas em um dataframe, podemos utilizar o método rename, ilustrado abaixo.
dados = dados.rename(columns={'coluna original': 'coluna renomeada'})
Vejamos na prática:
# Alterando nome de duas colunas:clientes_cifraonline = clientes_cifraonline.rename( columns = {'nivel_educacional': 'formacao', 'sexo': 'genero'})# Visualizando os resultados:clientes_cifraonline.head()
nome
idade
genero
salario
cidade
status_emprego
formacao
score_credito
0
João
62
M
R$ 6728
São Paulo
Desempregado
Mestrado
793
1
Mariano
65
M
R$ 7000
Porto Alegre
Autônomo
Pós-graduação
626
2
Luiz
71
M
R$ 6545
Rio de Janeiro
Autônomo
Graduação
438
3
Paula
18
F
R$ 3896
Salvador
Empregado
Ensino Médio
831
4
Carlo
21
M
R$ 12383
Salvador
Autônomo
Graduação
384
Tip
Caso desejemos eliminar colunas, podemos utilizar:
dados.drop(['coluna A'], axis=1, inplace=True)
2. Formatar textos
No conjunto de dados em questão, também temos nomes despadronizados (ora letras maiúsculas, ora minúsculas). Podemos lidar com esse tipo de situação (ver coluna nome) utilizando:
# Texto em minúsculo:clientes_cifraonline['nome'] = clientes_cifraonline['nome'].str.lower()clientes_cifraonline.head(2)
nome
idade
genero
salario
cidade
status_emprego
formacao
score_credito
0
joão
62
M
R$ 6728
São Paulo
Desempregado
Mestrado
793
1
mariano
65
M
R$ 7000
Porto Alegre
Autônomo
Pós-graduação
626
# Texto em maiúsculo:clientes_cifraonline['nome'] = clientes_cifraonline['nome'].str.upper()clientes_cifraonline.head(2)
nome
idade
genero
salario
cidade
status_emprego
formacao
score_credito
0
JOÃO
62
M
R$ 6728
São Paulo
Desempregado
Mestrado
793
1
MARIANO
65
M
R$ 7000
Porto Alegre
Autônomo
Pós-graduação
626
# Texto com Primeira Letra em Maiúsculo:clientes_cifraonline['nome'] = clientes_cifraonline['nome'].str.title()clientes_cifraonline.head(2)
nome
idade
genero
salario
cidade
status_emprego
formacao
score_credito
0
João
62
M
R$ 6728
São Paulo
Desempregado
Mestrado
793
1
Mariano
65
M
R$ 7000
Porto Alegre
Autônomo
Pós-graduação
626
3. Substituições
Frequentemente, vamos precisar substituir valores em um dataframe. Para isso, podemos utilizar o método .replace() conforme procede abaixo:
# Subsitutuição em todo o dataframe:dados = dados.replace('Valor original', 'Valor substituído')# Substituição em uma coluna específica:dados['coluna A'] = dados['coluna A'].replace('Valor original', 'Valor substituído')# Também funciona com números:dados['coluna A'] = dados['coluna A'].replace(0, 50)
No nosso caso, vamos adicionar alguns dados nulos em nosso dataframe com o auxílio da biblioteca numpy. Além disso, vamos criar uma variável numérica para genero, onde:
Aos clientes do gênero Feminino (F) será atribuídos o valor 0
Aos clientes do gênero Masculino (M) será atribuídos o valor 1
# Biblioteca numpy:import numpy as np# Adicionando nulos:clientes_cifraonline['score_credito'] = clientes_cifraonline['score_credito'].replace(793, np.nan).replace(831, np.nan).replace(719, np.nan)# Visualização dos resultadosclientes_cifraonline.isna().sum()/len(clientes_cifraonline)*100
nome 0.0
idade 0.0
genero 0.0
salario 0.0
cidade 0.0
status_emprego 0.0
formacao 0.0
score_credito 0.7
dtype: float64
Note que temos 0,7% de nulos no conjunto de dados agora.
# Codigicando a coluna gênero:clientes_cifraonline['genero_cod'] = clientes_cifraonline['genero'] # cópia da original# Outra opção é usar o `inplace`:clientes_cifraonline['genero_cod'].replace('F', 0, inplace=True)clientes_cifraonline['genero_cod'].replace('M', 1, inplace=True)# Visualização dos resultados:clientes_cifraonline[['nome', 'genero', 'genero_cod']].head(10)
nome
genero
genero_cod
0
João
M
1
1
Mariano
M
1
2
Luiz
M
1
3
Paula
F
0
4
Carlo
M
1
5
Luiz
M
1
6
Felipe
M
1
7
Ana
F
0
8
Paula
F
0
9
Paulo
M
1
4. Tratar nulos
Para o tratamento de nulos, poderímos usar algumas ténicas com o método .fillna().
# Preenchimento com 'zero':dados['coluna A'] = dados['coluna A'].fillna(0)# Preenchimento com a média:media_coluna_A = dados['Salário'].mean()dados['coluna A'] = dados['coluna A'].fillna(media_coluna_A)# Preenchimento com a mediana:mediana_coluna_A = dados['Salário'].median()dados['coluna A'] = dados['coluna A'].fillna(mediana_coluna_A)# Preenchimento com a moda:moda_coluna_A = dados['Salário'].mode()dados['coluna A'] = dados['coluna A'].fillna(moda_coluna_A)# Preenchimento com a texto:dados['coluna A'] = dados['coluna A'].fillna('Não informado')
Tip
Note que também poderíamos preencher nulos utilizando algoritmos de Machine Learning (e.g., K-Nearest Neighbors, Random Forest, IterativeImputer, etc.). Entretando, esse assunto foge do escopo desse curso e não iremos abordá-lo.
Como nesse caso os nulos representam apenas 0,7% do conjunto de dados, podemos apenas eliminar essas linhas.
# Total de linhas (originalmente):print(f'Total de linhas antes da remoçao de nulos: {clientes_cifraonline.shape[0]}')# Remoção de nulos:clientes_cifraonline.dropna(axis=0, inplace=True)# Impacto:print(f'Total de linhas após a remoçao de nulos: {clientes_cifraonline.shape[0]}')
Total de linhas antes da remoçao de nulos: 1000
Total de linhas após a remoçao de nulos: 993
5. Converter tipos de dados
No conjunto de dados em questão, notamos que a coluna salario está marcada como objeto. Isso se dá pois temos os caracteres ‘R$’, responsáveis por classificar a coluna salário como string. Para tratar essa coluna e obter valores numéricos, precisamos:
Remover caracteres especiais
Verificar separador decimal (se necessário, trocamos vírgula por ponto)
Converter o tipo de dado (object\(\rightarrow\)int) - métodos pd.to_numeric() e .astype().
# Removendo o prefixo 'R$' e os caracteres '.0' da coluna 'salario':clientes_cifraonline['salario'] = clientes_cifraonline['salario'].str.replace('R$', '')# Convertendo o tipo de dado para numérico, ignorando erros para lidar com valores não numéricos:clientes_cifraonline['salario'] = pd.to_numeric(clientes_cifraonline['salario'], errors='coerce')# Podemos converter esse inteiro para float:clientes_cifraonline['salario'] = clientes_cifraonline['salario'].astype('float64')clientes_cifraonline.head()
Podemos também criar funções previamente definias e aplicar ao conjunto de dados utilizando o método .apply().
# Função para categorizar score de créditodef categorizar_score(score):if score <500:return'Baixo'elif score <700:return'Médio'else:return'Alto'# Aplicar a função categorizar_score à coluna 'score_credito'clientes_cifraonline['faixa_score'] = clientes_cifraonline['score_credito'].apply(categorizar_score)# Resultado:clientes_cifraonline[['nome','genero','salario','score_credito','faixa_score']].head()
nome
genero
salario
score_credito
faixa_score
1
Mariano
M
7000.0
626
Médio
2
Luiz
M
6545.0
438
Baixo
4
Carlo
M
12383.0
384
Baixo
5
Luiz
M
1823.0
737
Alto
6
Felipe
M
1490.0
482
Baixo
Source Code
---title: "Manipulação de Dados com Pandas"author: "Vinícius Oviedo"format: bookup-html+darkonly: embed-fonts: true toc: true---# Limpeza de dadosNesta aula, vamos trabalhar com métodos aplicáveis à limpeza de dados com `Pandas`. Veremos os métodos para:1. Renomear colunas2. Formatar textos (minúsculo, maísculo, primeira letra em maiúscula)3. Realizar substituições com o método `.replace()`4. Tratar nulos - método `.fillna()`5. Converter tipos de dados em um *dataframe*6. Criar funções anônimas - função `lambda` e método `.apply()`.Esses tópicos são fundamentais em processos de ETL (***Extract, Transform and Load***) em projetos envolvendo dados. Ao longo desse módulos, vamos trabalhar com o conjunto de dados `` que trata de clientes da *CifraOnline*, um banco digital fictício com 1000 linhas.```{python}import pandas as pdclientes_cifraonline = pd.read_csv('dados/clientes-banco-cifraonline/clientes_cifraonline.csv')clientes_cifraonline.head()```Antes de inicar os tópicos, é importante notarmos que temos, dentre outras particularidades:1. Dados numéricos configurados como texto (coluna `salario`)2. Nomes despadronizados quanto à formatação (coluna `nome`).```{python}clientes_cifraonline.info()```## 1. Renomear colunasPara renomear colunas em um *dataframe*, podemos utilizar o método `rename`, ilustrado abaixo.```pythondados = dados.rename(columns={'coluna original': 'coluna renomeada'})```Vejamos na prática:```{python}# Alterando nome de duas colunas:clientes_cifraonline = clientes_cifraonline.rename( columns = {'nivel_educacional': 'formacao', 'sexo': 'genero'})# Visualizando os resultados:clientes_cifraonline.head()```::: {.callout-tip}##Caso desejemos eliminar colunas, podemos utilizar:```pythondados.drop(['coluna A'], axis=1, inplace=True)```:::## 2. Formatar textosNo conjunto de dados em questão, também temos nomes despadronizados (ora letras maiúsculas, ora minúsculas). Podemos lidar com esse tipo de situação (ver coluna `nome`) utilizando:```{python}# Texto em minúsculo:clientes_cifraonline['nome'] = clientes_cifraonline['nome'].str.lower()clientes_cifraonline.head(2)``````{python}# Texto em maiúsculo:clientes_cifraonline['nome'] = clientes_cifraonline['nome'].str.upper()clientes_cifraonline.head(2)``````{python}# Texto com Primeira Letra em Maiúsculo:clientes_cifraonline['nome'] = clientes_cifraonline['nome'].str.title()clientes_cifraonline.head(2)```## 3. SubstituiçõesFrequentemente, vamos precisar substituir valores em um *dataframe*. Para isso, podemos utilizar o método `.replace()` conforme procede abaixo:```python# Subsitutuição em todo o dataframe:dados = dados.replace('Valor original', 'Valor substituído')# Substituição em uma coluna específica:dados['coluna A'] = dados['coluna A'].replace('Valor original', 'Valor substituído')# Também funciona com números:dados['coluna A'] = dados['coluna A'].replace(0, 50)```No nosso caso, vamos adicionar alguns dados nulos em nosso dataframe com o auxílio da biblioteca `numpy`. Além disso, vamos criar uma variável numérica para `genero`, onde:1. Aos clientes do gênero **Feminino (F)** será atribuídos o valor **0**2. Aos clientes do gênero **Masculino (M)** será atribuídos o valor **1**```{python}# Biblioteca numpy:import numpy as np# Adicionando nulos:clientes_cifraonline['score_credito'] = clientes_cifraonline['score_credito'].replace(793, np.nan).replace(831, np.nan).replace(719, np.nan)# Visualização dos resultadosclientes_cifraonline.isna().sum()/len(clientes_cifraonline)*100```> Note que temos 0,7% de nulos no conjunto de dados agora.```{python}# Codigicando a coluna gênero:clientes_cifraonline['genero_cod'] = clientes_cifraonline['genero'] # cópia da original# Outra opção é usar o `inplace`:clientes_cifraonline['genero_cod'].replace('F', 0, inplace=True)clientes_cifraonline['genero_cod'].replace('M', 1, inplace=True)# Visualização dos resultados:clientes_cifraonline[['nome', 'genero', 'genero_cod']].head(10)```## 4. Tratar nulosPara o tratamento de nulos, poderímos usar algumas ténicas com o método `.fillna()`.```python# Preenchimento com 'zero':dados['coluna A'] = dados['coluna A'].fillna(0)# Preenchimento com a média:media_coluna_A = dados['Salário'].mean()dados['coluna A'] = dados['coluna A'].fillna(media_coluna_A)# Preenchimento com a mediana:mediana_coluna_A = dados['Salário'].median()dados['coluna A'] = dados['coluna A'].fillna(mediana_coluna_A)# Preenchimento com a moda:moda_coluna_A = dados['Salário'].mode()dados['coluna A'] = dados['coluna A'].fillna(moda_coluna_A)# Preenchimento com a texto:dados['coluna A'] = dados['coluna A'].fillna('Não informado')```::: {.callout-tip}##Note que também poderíamos preencher nulos utilizando algoritmos de **Machine Learning** (e.g., *K-Nearest Neighbors*, *Random Forest*, *IterativeImputer*, etc.). Entretando, esse assunto foge do escopo desse curso e não iremos abordá-lo.:::Como nesse caso os nulos representam apenas **0,7%** do conjunto de dados, podemos apenas eliminar essas linhas.```{python}# Total de linhas (originalmente):print(f'Total de linhas antes da remoçao de nulos: {clientes_cifraonline.shape[0]}')# Remoção de nulos:clientes_cifraonline.dropna(axis=0, inplace=True)# Impacto:print(f'Total de linhas após a remoçao de nulos: {clientes_cifraonline.shape[0]}')```## 5. Converter tipos de dadosNo conjunto de dados em questão, notamos que a coluna `salario` está marcada como objeto. Isso se dá pois temos os caracteres '**R$**', responsáveis por classificar a coluna salário como *string*. Para tratar essa coluna e obter valores numéricos, precisamos:1. Remover caracteres especiais2. Verificar separador decimal (se necessário, trocamos vírgula por ponto)3. Converter o tipo de dado (*object* $\rightarrow$ *int*) - métodos `pd.to_numeric()` e `.astype()`.Métodos:```python# método 1:dados['coluna A'] = pd.to_numeric(dados['coluna A'], errors='coerce')# método 2:dados['coluna A'] = dados['coluna A'].astype('float64')```Na prática, temos:```{python}# Removendo o prefixo 'R$' e os caracteres '.0' da coluna 'salario':clientes_cifraonline['salario'] = clientes_cifraonline['salario'].str.replace('R$', '')# Convertendo o tipo de dado para numérico, ignorando erros para lidar com valores não numéricos:clientes_cifraonline['salario'] = pd.to_numeric(clientes_cifraonline['salario'], errors='coerce')# Podemos converter esse inteiro para float:clientes_cifraonline['salario'] = clientes_cifraonline['salario'].astype('float64')clientes_cifraonline.head()```Da mesma maneira, score poderia ser um inteiro:```{python}# Conversão:clientes_cifraonline['score_credito'] = clientes_cifraonline['score_credito'].astype('int64')# Resultado:clientes_cifraonline.head()```## 6. Funções anônimasOutra possilibdade é a utilização de funções anônimas - famosa função `lambda`. A sintaxe é dada por:```python(lambda<variavel(eis)>: <expressao>)```Vamos supor que desejamos anualizar o salários do clientes, logo poderíamos aplicar uma função `lambda`:```{python}# Cópia de `salario`:clientes_cifraonline['salario_anual'] = clientes_cifraonline['salario']# Anualizando `salario`:clientes_cifraonline['salario_anual'] = clientes_cifraonline['salario_anual'].apply(lambda salario: salario *12)clientes_cifraonline[['salario', 'salario_anual']].head()```No caso da codificação do gênero, também poderia ser feita com uma função anônima:```{python}# Codificação utilizando função anônima:clientes_cifraonline['genero_cod_lambda'] = clientes_cifraonline['genero'].apply(lambda registro: 0if registro =='F'else1)# Resultado:clientes_cifraonline[['genero', 'genero_cod_lambda']].tail()```Podemos também criar funções previamente definias e aplicar ao conjunto de dados utilizando o método `.apply()`.```{python}# Função para categorizar score de créditodef categorizar_score(score):if score <500:return'Baixo'elif score <700:return'Médio'else:return'Alto'# Aplicar a função categorizar_score à coluna 'score_credito'clientes_cifraonline['faixa_score'] = clientes_cifraonline['score_credito'].apply(categorizar_score)# Resultado:clientes_cifraonline[['nome','genero','salario','score_credito','faixa_score']].head()```