Dominando a arte da limpeza de dados em Python - KDnuggets

Dominando a arte da limpeza de dados em Python – KDnuggets

Nó Fonte: 2939047

Dominando a arte da limpeza de dados em Python
Imagem do autor
 

A limpeza de dados é uma parte crítica de qualquer processo de análise de dados. É a etapa em que você remove erros, lida com dados ausentes e garante que seus dados estejam em um formato com o qual você possa trabalhar. Sem um conjunto de dados bem limpo, quaisquer análises subsequentes podem ser distorcidas ou incorretas.

Este artigo apresenta várias técnicas importantes para limpeza de dados em Python, usando bibliotecas poderosas como pandas, numpy, seaborn e matplotlib.

Antes de mergulharmos na mecânica da limpeza de dados, vamos entender sua importância. Os dados do mundo real costumam ser confusos. Pode conter entradas duplicadas, tipos de dados incorretos ou inconsistentes, valores ausentes, recursos irrelevantes e valores discrepantes. Todos esses fatores podem levar a conclusões enganosas na análise dos dados. Isso torna a limpeza de dados uma parte indispensável do ciclo de vida da ciência de dados.

Abordaremos as seguintes tarefas de limpeza de dados.
 

Dominando a arte da limpeza de dados em Python
Imagem do autor

Antes de começar, vamos importar as bibliotecas necessárias. Usaremos pandas para manipulação de dados e seaborn e matplotlib para visualizações.

Também importaremos o módulo datetime Python para manipular as datas.

import pandas as pd
import seaborn as sns
import datetime as dt
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

Primeiro, precisaremos carregar nossos dados. Neste exemplo, carregaremos um arquivo CSV usando pandas. Também adicionamos o argumento delimitador.

df = pd.read_csv('F:KDNuggetsKDN Mastering the Art of Data Cleaning in Pythonproperty.csv', delimiter= ';')

Em seguida, é importante inspecionar os dados para entender sua estrutura, com que tipo de variáveis ​​estamos trabalhando e se há algum valor faltante. Como os dados que importamos não são enormes, vamos dar uma olhada em todo o conjunto de dados.

# Look at all the rows of the dataframe
display(df)

Esta é a aparência do conjunto de dados.

 

Dominando a arte da limpeza de dados em Python
 

Você pode ver imediatamente que há alguns valores ausentes. Além disso, os formatos de data são inconsistentes.

Agora, vamos dar uma olhada no resumo do DataFrame usando o método info().

# Get a concise summary of the dataframe
print(df.info())

Aqui está a saída do código.

 

Dominando a arte da limpeza de dados em Python
 

Podemos ver que apenas a coluna square_feet não possui nenhum valor NULL, então teremos que lidar com isso de alguma forma. Além disso, as colunas data_anúncio e data_venda são do tipo de dados do objeto, embora deva ser uma data.

A localização da coluna está completamente vazia. Precisamos disso?

Mostraremos como lidar com esses problemas. Começaremos aprendendo como excluir colunas desnecessárias.

Existem duas colunas no conjunto de dados que não precisamos em nossa análise de dados, portanto, iremos removê-las.

A primeira coluna é comprador. Não precisamos disso, pois o nome do comprador não impacta na análise.

Estamos usando o método drop() com o nome da coluna especificado. Definimos o eixo como 1 para especificar que queremos excluir uma coluna. Além disso, o argumento inplace é definido como True para que modifiquemos o DataFrame existente e não criemos um novo DataFrame sem a coluna removida.

df.drop('buyer', axis = 1, inplace = True)

A segunda coluna que queremos remover é a localização. Embora possa ser útil ter essas informações, esta é uma coluna completamente vazia, então vamos removê-la.

Adotamos a mesma abordagem da primeira coluna.

df.drop('location', axis = 1, inplace = True)

Claro, você pode remover essas duas colunas simultaneamente.

df = df.drop(['buyer', 'location'], axis=1)

Ambas as abordagens retornam o seguinte dataframe.

 

Dominando a arte da limpeza de dados em Python

Dados duplicados podem ocorrer em seu conjunto de dados por vários motivos e podem distorcer sua análise.

Vamos detectar as duplicatas em nosso conjunto de dados. Veja como fazer isso.

O código abaixo usa o método duplicado() considerar duplicatas em todo o conjunto de dados. Sua configuração padrão é considerar a primeira ocorrência de um valor como única e as ocorrências subsequentes como duplicadas. Você pode modificar esse comportamento usando o manter parâmetro. Por exemplo, df.duplicated(keep=False) marcaria todas as duplicatas como True, incluindo a primeira ocorrência.

# Detecting duplicates
duplicates = df[df.duplicated()]
duplicates

Aqui está a saída.

 

Dominando a arte da limpeza de dados em Python
 

A linha com índice 3 foi marcada como duplicada porque a linha 2 com os mesmos valores é sua primeira ocorrência.

Agora precisamos remover duplicatas, o que fazemos com o código a seguir.

# Detecting duplicates
duplicates = df[df.duplicated()]
duplicates

A drop_duplicados() A função considera todas as colunas enquanto identifica duplicatas. Se você quiser considerar apenas certas colunas, você pode passá-las como uma lista para esta função como esta: df.drop_duplicates(subset=['column1', 'column2']).

 

Dominando a arte da limpeza de dados em Python
 

Como você pode ver, a linha duplicada foi eliminada. No entanto, a indexação permaneceu a mesma, faltando o índice 3. Vamos arrumar isso redefinindo os índices.

df = df.reset_index(drop=True)

Esta tarefa é executada usando o reset_index() função. O argumento drop=True é usado para descartar o índice original. Se você não incluir este argumento, o índice antigo será adicionado como uma nova coluna no seu DataFrame. Ao definir drop=True, você está dizendo ao pandas para esquecer o índice antigo e redefini-lo para o índice inteiro padrão.

Para praticar, tente remova duplicatas deste conjunto de dados da Microsoft.

Às vezes, os tipos de dados podem estar configurados incorretamente. Por exemplo, uma coluna de data pode ser interpretada como strings. Você precisa convertê-los em seus tipos apropriados.

Em nosso conjunto de dados, faremos isso para as colunas data_propaganda e data_venda, pois elas são mostradas como o tipo de dados do objeto. Além disso, as datas são formatadas de forma diferente nas linhas. Precisamos torná-lo consistente, além de convertê-lo até o momento.

A maneira mais fácil é usar o até_datahora() método. Novamente, você pode fazer isso coluna por coluna, conforme mostrado abaixo.

Ao fazer isso, definimos o argumento dayfirst como True porque algumas datas começam com o dia primeiro.

# Converting advertisement_date column to datetime
df['advertisement_date'] = pd.to_datetime(df['advertisement_date'], dayfirst = True) # Converting sale_date column to datetime
df['sale_date'] = pd.to_datetime(df['sale_date'], dayfirst = True)

Você também pode converter as duas colunas ao mesmo tempo usando o comando Aplique() método com até_datahora().

# Converting advertisement_date and sale_date columns to datetime
df[['advertisement_date', 'sale_date']] = df[['advertisement_date', 'sale_date']].apply(pd.to_datetime, dayfirst = True)

Ambas as abordagens fornecem o mesmo resultado.

 

Dominando a arte da limpeza de dados em Python
 

Agora as datas estão em um formato consistente. Vemos que nem todos os dados foram convertidos. Há um valor NaT em warning_date e dois em sale_date. Isso significa que a data está faltando.

Vamos verificar se as colunas são convertidas em datas usando o info () método.

# Get a concise summary of the dataframe
print(df.info())

 

Dominando a arte da limpeza de dados em Python
 

Como você pode ver, ambas as colunas não estão no formato datetime64[ns].

Agora, tente converter os dados de TEXT para NUMERIC neste Conjunto de dados do Airbnb.

Os conjuntos de dados do mundo real geralmente apresentam valores ausentes. O tratamento de dados ausentes é vital, pois certos algoritmos não conseguem lidar com tais valores.

Nosso exemplo também possui alguns valores ausentes, então vamos dar uma olhada nas duas abordagens mais comuns para lidar com dados ausentes.

Excluindo linhas com valores ausentes

Se o número de linhas com dados faltantes for insignificante em comparação com o número total de observações, considere excluir essas linhas.

Em nosso exemplo, a última linha não possui valores, exceto os pés quadrados e a data do anúncio. Não podemos usar esses dados, então vamos remover esta linha.

Aqui está o código onde indicamos o índice da linha.

df = df.drop(8)

O DataFrame agora se parece com isto.

 

Dominando a arte da limpeza de dados em Python
 

A última linha foi excluída e nosso DataFrame agora parece melhor. No entanto, ainda existem alguns dados faltantes que iremos tratar usando outra abordagem.

Imputando valores ausentes

Se você tiver dados faltantes significativos, uma estratégia melhor do que a exclusão poderia ser a imputação. Este processo envolve o preenchimento de valores ausentes com base em outros dados. Para dados numéricos, os métodos de imputação comuns envolvem o uso de uma medida de tendência central (média, mediana, moda).

Em nosso DataFrame já alterado, temos valores NaT (Not a Time) nas colunas warning_date e sale_date. Iremos imputar esses valores ausentes usando o significar() método.

O código usa o preencher() método para encontrar e preencher os valores nulos com o valor médio.

# Imputing values for numerical columns
df['advertisement_date'] = df['advertisement_date'].fillna(df['advertisement_date'].mean())
df['sale_date'] = df['sale_date'].fillna(df['sale_date'].mean())

Você também pode fazer a mesma coisa em uma linha de código. Nós usamos o Aplique() para aplicar a função definida usando lambda. Assim como acima, esta função usa o preencher() e significar() métodos para preencher os valores ausentes.

# Imputing values for multiple numerical columns
df[['advertisement_date', 'sale_date']] = df[['advertisement_date', 'sale_date']].apply(lambda x: x.fillna(x.mean()))

A saída em ambos os casos é semelhante a esta.

 

Dominando a arte da limpeza de dados em Python
 

Nossa coluna sale_date agora tem horários que não precisamos. Vamos removê-los.

Vamos usar o strftime () método, que converte as datas em sua representação de string e um formato específico.

df['sale_date'] = df['sale_date'].dt.strftime('%Y-%m-%d')

 

Dominando a arte da limpeza de dados em Python
 

As datas agora parecem todas arrumadas.

Se você precisa usar strftime () em várias colunas, você pode usar novamente lambda da seguinte maneira.

df[['date1_formatted', 'date2_formatted']] = df[['date1', 'date2']].apply(lambda x: x.dt.strftime('%Y-%m-%d'))

Agora, vamos ver como podemos imputar valores categóricos ausentes.

Dados categóricos são um tipo de dados usados ​​para agrupar informações com características semelhantes. Cada um desses grupos é uma categoria. Os dados categóricos podem assumir valores numéricos (como “1” indicando “masculino” e “2” indicando “feminino”), mas esses números não têm significado matemático. Você não pode adicioná-los, por exemplo.

Os dados categóricos são normalmente divididos em duas categorias:

  1. Dados nominais: Isto ocorre quando as categorias são apenas rotuladas e não podem ser organizadas em nenhuma ordem específica. Os exemplos incluem sexo (masculino, feminino), tipo sanguíneo (A, B, AB, O) ou cor (vermelho, verde, azul).
  1. Dados ordinais: É quando as categorias podem ser ordenadas ou classificadas. Embora os intervalos entre as categorias não sejam igualmente espaçados, a ordem das categorias tem um significado. Os exemplos incluem escalas de classificação (classificação de 1 a 5 de um filme), um nível de escolaridade (ensino médio, graduação, pós-graduação) ou estágios do câncer (Estágio I, Estágio II, Estágio III).

Para imputar dados categóricos ausentes, o modo é normalmente usado. Em nosso exemplo, a coluna property_category contém dados categóricos (nominais) e há dados faltando em duas linhas.

Vamos substituir os valores ausentes pela moda.

# For categorical columns
df['property_category'] = df['property_category'].fillna(df['property_category'].mode()[0])

Este código usa o preencher() função para substituir todos os valores NaN na coluna property_category. Ele o substitui pelo modo.

Além disso, a parte [0] é usada para extrair o primeiro valor desta série. Se houver vários modos, isso selecionará o primeiro. Se houver apenas um modo, ainda funciona bem.

Aqui está a saída.

 

Dominando a arte da limpeza de dados em Python
 

Os dados agora parecem muito bons. A única coisa que resta é ver se há valores discrepantes.

Você pode praticar como lidar com nulos neste Pergunta da meta entrevista, onde você terá que substituir NULLs por zeros.

Outliers são pontos de dados em um conjunto de dados que são distintamente diferentes de outras observações. Eles podem estar excepcionalmente distantes dos outros valores no conjunto de dados, residindo fora de um padrão geral. Eles são considerados incomuns porque seus valores são significativamente maiores ou menores em comparação com o restante dos dados.

Outliers podem surgir devido a vários motivos, como:

  • Erros de medição ou entrada
  • Corrupção de dados
  • Verdadeiras anomalias estatísticas

Valores discrepantes podem impactar significativamente os resultados de sua análise de dados e modelagem estatística. Eles podem levar a uma distribuição distorcida, enviesada ou invalidar as suposições estatísticas subjacentes, distorcer o ajuste estimado do modelo, reduzir a precisão preditiva dos modelos preditivos e levar a conclusões incorretas.

Alguns métodos comumente usados ​​para detectar valores discrepantes são pontuação Z, IQR (intervalo interquartil), gráficos de caixa, gráficos de dispersão e técnicas de visualização de dados. Em alguns casos avançados, métodos de aprendizado de máquina também são usados.

A visualização de dados pode ajudar a identificar valores discrepantes. O boxplot de Seaborn é útil para isso.

plt.figure(figsize=(10, 6))
sns.boxplot(data=df[['advertised_price', 'sale_price']])

Usamos plt.figure() para definir a largura e a altura da figura em polegadas.

Em seguida, criamos o boxplot para as colunas preço_anunciado e preço_venda, que se parece com isto.

 

Dominando a arte da limpeza de dados em Python
 

O gráfico pode ser melhorado para facilitar o uso adicionando-o ao código acima.

plt.xlabel('Prices')
plt.ylabel('USD')
plt.ticklabel_format(style='plain', axis='y')
formatter = ticker.FuncFormatter(lambda x, p: format(x, ',.2f'))
plt.gca().yaxis.set_major_formatter(formatter)

Usamos o código acima para definir os rótulos para ambos os eixos. Notamos também que os valores no eixo y estão na notação científica e não podemos usar isso para os valores dos preços. Então, mudamos isso para o estilo simples usando a função plt.ticklabel_format().

Em seguida, criamos o formatador que mostrará os valores no eixo y com vírgulas como separadores de milhar e pontos decimais. A última linha de código aplica isso ao eixo.

A saída agora se parece com esta.

 

Dominando a arte da limpeza de dados em Python
 

Agora, como identificamos e removemos o outlier?

Uma das maneiras é usar o método IQR.

IQR, ou intervalo interquartil, é um método estatístico usado para medir a variabilidade dividindo um conjunto de dados em quartis. Os quartis dividem um conjunto de dados ordenados por classificação em quatro partes iguais, e os valores dentro do intervalo do primeiro quartil (percentil 25) e do terceiro quartil (percentil 75) constituem o intervalo interquartil.

O intervalo interquartil é usado para identificar valores discrepantes nos dados. Veja como funciona:

  1. Primeiro, calcule o primeiro quartil (Q1), o terceiro quartil (Q3) e depois determine o IQR. O IQR é calculado como Q3 – Q1.
  2. Qualquer valor abaixo de Q1 – 1.5IQR ou acima de Q3 + 1.5IQR é considerado um outlier.

Em nosso boxplot, a caixa na verdade representa o IQR. A linha dentro da caixa é a mediana (ou segundo quartil). Os 'bigodes' do boxplot representam o intervalo dentro de 1.5*IQR de Q1 e Q3.

Quaisquer pontos de dados fora desses bigodes podem ser considerados discrepantes. No nosso caso, é o valor de $ 12,000,000. Se você observar o boxplot, verá como isso é claramente representado, o que mostra por que a visualização de dados é importante na detecção de valores discrepantes.

Agora, vamos remover os valores discrepantes usando o método IQR no código Python. Primeiro, removeremos os valores discrepantes dos preços anunciados.

Q1 = df['advertised_price'].quantile(0.25)
Q3 = df['advertised_price'].quantile(0.75)
IQR = Q3 - Q1
df = df[~((df['advertised_price'] (Q1 - 1.5 * IQR)) |(df['advertised_price'] > (Q3 + 1.5 * IQR)))]

Primeiro calculamos o primeiro quartil (ou o 25º percentil) usando o quantil() função. Fazemos o mesmo para o terceiro quartil ou percentil 75.

Eles mostram os valores abaixo dos quais caem 25% e 75% dos dados, respectivamente.

Em seguida, calculamos a diferença entre os quartis. Tudo até agora é apenas traduzir as etapas do IQR em código Python.

Como etapa final, removemos os outliers. Em outras palavras, todos os dados inferiores a Q1 – 1.5 * IQR ou superiores a Q3 + 1.5 * IQR.

O operador '~' nega a condição, então ficamos apenas com os dados que não são discrepantes.

Então podemos fazer o mesmo com o preço de venda.

Q1 = df['sale_price'].quantile(0.25)
Q3 = df['sale_price'].quantile(0.75)
IQR = Q3 - Q1
df = df[~((df['sale_price'] (Q1 - 1.5 * IQR)) |(df['sale_price'] > (Q3 + 1.5 * IQR)))]

Claro, você pode fazer isso de uma forma mais sucinta usando o para laço.

for column in ['advertised_price', 'sale_price']: Q1 = df[column].quantile(0.25) Q3 = df[column].quantile(0.75) IQR = Q3 - Q1 df = df[~((df[column] (Q1 - 1.5 * IQR)) |(df[column] > (Q3 + 1.5 * IQR)))]

O loop itera das duas colunas. Para cada coluna, calcula o IQR e depois remove as linhas do DataFrame.

Observe que esta operação é feita sequencialmente, primeiro para preço_anunciado e depois para preço_de_venda. Como resultado, o DataFrame é modificado no local para cada coluna e as linhas podem ser removidas por serem discrepantes em qualquer coluna. Portanto, esta operação poderá resultar em menos linhas do que se os valores discrepantes para o preço_anunciado e o preço_de_venda fossem removidos independentemente e os resultados fossem combinados posteriormente.

No nosso exemplo, a saída será a mesma em ambos os casos. Para ver como o box plot mudou, precisamos plotá-lo novamente usando o mesmo código anterior.

plt.figure(figsize=(10, 6))
sns.boxplot(data=df[['advertised_price', 'sale_price']])
plt.xlabel('Prices')
plt.ylabel('USD')
plt.ticklabel_format(style='plain', axis='y')
formatter = ticker.FuncFormatter(lambda x, p: format(x, ',.2f'))
plt.gca().yaxis.set_major_formatter(formatter)

Aqui está a saída.

 

Dominando a arte da limpeza de dados em Python
 

Você pode praticar o cálculo de percentis em Python resolvendo o problema Pergunta da entrevista da Assembleia Geral.

A limpeza de dados é uma etapa crucial no processo de análise de dados. Embora possa ser demorado, é essencial garantir a precisão de suas descobertas.

Felizmente, o rico ecossistema de bibliotecas do Python torna esse processo mais gerenciável. Aprendemos como remover linhas e colunas desnecessárias, reformatar dados e lidar com valores ausentes e discrepantes. Estas são as etapas usuais que devem ser executadas na maioria dos dados. No entanto, às vezes você também precisará combinar duas colunas em uma, verificar os dados existentes, atribuir rótulos a eleou livrar-se dos espaços em branco.

Tudo isso é limpeza de dados, pois permite transformar dados confusos do mundo real em um conjunto de dados bem estruturado que você pode analisar com confiança. Basta comparar o conjunto de dados com o qual começamos com aquele com o qual terminamos.

Se você não vê satisfação neste resultado e os dados limpos não o deixam estranhamente animado, o que diabos você está fazendo em ciência de dados!?
 

Nate Rosidi é cientista de dados e em estratégia de produto. Ele também é professor adjunto ensinando análise e é o fundador da StrataScratchGenericName, uma plataforma que ajuda os cientistas de dados a se prepararem para suas entrevistas com perguntas reais das principais empresas. Conecte-se com ele em Twitter: StrataScratch or LinkedIn.

Carimbo de hora:

Mais de KDnuggetsGenericName