Folha de dicas do bloco de notas para pré-processamento rápido de dados

Freqüentemente, as pessoas que entram no campo da Ciência de Dados têm expectativas nada realistas sobre o que as espera. Muitas pessoas pensam que agora escreverão redes neurais legais, criarão um assistente de voz do Homem de Ferro ou vencerão todos nos mercados financeiros.
Mas trabalhe Data O cientista é orientado por dados, e um dos aspectos mais importantes e demorados é processar os dados antes de alimentá-los em uma rede neural ou analisá-los de uma determinada maneira.

Neste artigo, nossa equipe descreverá como você pode processar dados de forma rápida e fácil com instruções e código passo a passo. Tentamos tornar o código bastante flexível e poder ser usado para diferentes conjuntos de dados.

Muitos profissionais podem não encontrar nada de extraordinário neste artigo, mas os iniciantes poderão aprender algo novo, e qualquer pessoa que há muito sonha em fazer um notebook separado para processamento de dados rápido e estruturado pode copiar o código e formatá-lo para si mesmo, ou baixe o notebook finalizado do Github.

Recebemos o conjunto de dados. o que fazer a seguir?

Então, o padrão: precisamos entender com o que estamos lidando, o quadro geral. Para fazer isso, usamos pandas para simplesmente definir diferentes tipos de dados.

import pandas as pd #импортируем pandas
import numpy as np  #импортируем numpy
df = pd.read_csv("AB_NYC_2019.csv") #читаем датасет и записываем в переменную df

df.head(3) #смотрим на первые 3 строчки, чтобы понять, как выглядят значения

Folha de dicas do bloco de notas para pré-processamento rápido de dados

df.info() #Демонстрируем информацию о колонках

Folha de dicas do bloco de notas para pré-processamento rápido de dados

Vejamos os valores das colunas:

  1. O número de linhas em cada coluna corresponde ao número total de linhas?
  2. Qual é a essência dos dados em cada coluna?
  3. Qual coluna queremos atingir para fazer previsões sobre ela?

As respostas a essas perguntas permitirão que você analise o conjunto de dados e trace um plano para suas próximas ações.

Além disso, para uma análise mais aprofundada dos valores em cada coluna, podemos usar a função pandasscribe(). No entanto, a desvantagem desta função é que ela não fornece informações sobre colunas com valores de string. Trataremos deles mais tarde.

df.describe()

Folha de dicas do bloco de notas para pré-processamento rápido de dados

Visualização mágica

Vejamos onde não temos nenhum valor:

import seaborn as sns
sns.heatmap(df.isnull(),yticklabels=False,cbar=False,cmap='viridis')

Folha de dicas do bloco de notas para pré-processamento rápido de dados

Esta foi uma breve olhada de cima, agora passaremos para coisas mais interessantes

Vamos tentar encontrar e, se possível, remover colunas que possuem apenas um valor em todas as linhas (elas não afetarão o resultado de forma alguma):

df = df[[c for c
        in list(df)
        if len(df[c].unique()) > 1]] #Перезаписываем датасет, оставляя только те колонки, в которых больше одного уникального значения

Agora protegemos a nós mesmos e ao sucesso do nosso projeto contra linhas duplicadas (linhas que contêm as mesmas informações na mesma ordem de uma das linhas existentes):

df.drop_duplicates(inplace=True) #Делаем это, если считаем нужным.
                                 #В некоторых проектах удалять такие данные с самого начала не стоит.

Dividimos o conjunto de dados em dois: um com valores qualitativos e outro com valores quantitativos

Aqui precisamos fazer um pequeno esclarecimento: se as linhas com dados faltantes em dados qualitativos e quantitativos não estão muito correlacionadas entre si, então precisaremos decidir o que sacrificamos - todas as linhas com dados faltantes, apenas parte delas, ou certas colunas. Se as linhas estiverem correlacionadas, temos todo o direito de dividir o conjunto de dados em dois. Caso contrário, primeiro você precisará lidar com as linhas que não correlacionam os dados faltantes em termos qualitativos e quantitativos, e só então dividir o conjunto de dados em dois.

df_numerical = df.select_dtypes(include = [np.number])
df_categorical = df.select_dtypes(exclude = [np.number])

Fazemos isso para facilitar o processamento desses dois tipos diferentes de dados - mais tarde entenderemos o quanto isso facilita a nossa vida.

Trabalhamos com dados quantitativos

A primeira coisa que devemos fazer é determinar se existem “colunas de espionagem” nos dados quantitativos. Chamamos essas colunas assim porque se apresentam como dados quantitativos, mas atuam como dados qualitativos.

Como podemos identificá-los? Claro, tudo depende da natureza dos dados que você está analisando, mas em geral essas colunas podem ter poucos dados exclusivos (na região de 3 a 10 valores exclusivos).

print(df_numerical.nunique())

Depois de identificarmos as colunas espiãs, iremos movê-las de dados quantitativos para dados qualitativos:

spy_columns = df_numerical[['колонка1', 'колока2', 'колонка3']]#выделяем колонки-шпионы и записываем в отдельную dataframe
df_numerical.drop(labels=['колонка1', 'колока2', 'колонка3'], axis=1, inplace = True)#вырезаем эти колонки из количественных данных
df_categorical.insert(1, 'колонка1', spy_columns['колонка1']) #добавляем первую колонку-шпион в качественные данные
df_categorical.insert(1, 'колонка2', spy_columns['колонка2']) #добавляем вторую колонку-шпион в качественные данные
df_categorical.insert(1, 'колонка3', spy_columns['колонка3']) #добавляем третью колонку-шпион в качественные данные

Finalmente, separamos completamente os dados quantitativos dos dados qualitativos e agora podemos trabalhar com eles de maneira adequada. A primeira coisa é entender onde temos valores vazios (NaN, e em alguns casos 0 será aceito como valores vazios).

for i in df_numerical.columns:
    print(i, df[i][df[i]==0].count())

Neste ponto, é importante entender em quais colunas os zeros podem indicar valores faltantes: isso se deve à forma como os dados foram coletados? Ou poderia estar relacionado aos valores dos dados? Essas perguntas devem ser respondidas caso a caso.

Portanto, se ainda decidirmos que podemos estar faltando dados onde há zeros, devemos substituir os zeros por NaN para facilitar o trabalho posterior com esses dados perdidos:

df_numerical[["колонка 1", "колонка 2"]] = df_numerical[["колонка 1", "колонка 2"]].replace(0, nan)

Agora vamos ver onde estão faltando dados:

sns.heatmap(df_numerical.isnull(),yticklabels=False,cbar=False,cmap='viridis') # Можно также воспользоваться df_numerical.info()

Folha de dicas do bloco de notas para pré-processamento rápido de dados

Aqui os valores que faltam dentro das colunas devem ser marcados em amarelo. E agora começa a diversão – como lidar com esses valores? Devo excluir linhas com esses valores ou colunas? Ou preencher esses valores vazios com outros?

Aqui está um diagrama aproximado que pode ajudá-lo a decidir o que pode, em princípio, ser feito com valores vazios:

Folha de dicas do bloco de notas para pré-processamento rápido de dados

0. Remova colunas desnecessárias

df_numerical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True)

1. O número de valores vazios nesta coluna é superior a 50%?

print(df_numerical.isnull().sum() / df_numerical.shape[0] * 100)

df_numerical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True)#Удаляем, если какая-то колонка имеет больше 50 пустых значений

2. Exclua linhas com valores vazios

df_numerical.dropna(inplace=True)#Удаляем строчки с пустыми значениями, если потом останется достаточно данных для обучения

3.1. Inserindo um valor aleatório

import random #импортируем random
df_numerical["колонка"].fillna(lambda x: random.choice(df[df[column] != np.nan]["колонка"]), inplace=True) #вставляем рандомные значения в пустые клетки таблицы

3.2. Inserindo um valor constante

from sklearn.impute import SimpleImputer #импортируем SimpleImputer, который поможет вставить значения
imputer = SimpleImputer(strategy='constant', fill_value="<Ваше значение здесь>") #вставляем определенное значение с помощью SimpleImputer
df_numerical[["новая_колонка1",'новая_колонка2','новая_колонка3']] = imputer.fit_transform(df_numerical[['колонка1', 'колонка2', 'колонка3']]) #Применяем это для нашей таблицы
df_numerical.drop(labels = ["колонка1","колонка2","колонка3"], axis = 1, inplace = True) #Убираем колонки со старыми значениями

3.3. Insira o valor médio ou mais frequente

from sklearn.impute import SimpleImputer #импортируем SimpleImputer, который поможет вставить значения
imputer = SimpleImputer(strategy='mean', missing_values = np.nan) #вместо mean можно также использовать most_frequent
df_numerical[["новая_колонка1",'новая_колонка2','новая_колонка3']] = imputer.fit_transform(df_numerical[['колонка1', 'колонка2', 'колонка3']]) #Применяем это для нашей таблицы
df_numerical.drop(labels = ["колонка1","колонка2","колонка3"], axis = 1, inplace = True) #Убираем колонки со старыми значениями

3.4. Insira o valor calculado por outro modelo

Às vezes, os valores podem ser calculados usando modelos de regressão usando modelos da biblioteca sklearn ou outras bibliotecas semelhantes. Nossa equipe dedicará um artigo separado sobre como isso pode ser feito em um futuro próximo.

Então, por enquanto, a narrativa sobre dados quantitativos será interrompida, porque existem muitas outras nuances sobre como fazer melhor a preparação e o pré-processamento de dados para diferentes tarefas, e os aspectos básicos para dados quantitativos foram levados em consideração neste artigo, e agora é a hora de retornar aos dados qualitativos, que separamos vários passos dos quantitativos. Você pode alterar este caderno como quiser, adaptando-o às diferentes tarefas, para que o pré-processamento dos dados seja muito rápido!

Dados qualitativos

Basicamente, para dados qualitativos, o método One-hot-encoding é usado para formatá-los de uma string (ou objeto) para um número. Antes de passarmos a este ponto, vamos usar o diagrama e o código acima para lidar com valores vazios.

df_categorical.nunique()

sns.heatmap(df_categorical.isnull(),yticklabels=False,cbar=False,cmap='viridis')

Folha de dicas do bloco de notas para pré-processamento rápido de dados

0. Remova colunas desnecessárias

df_categorical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True)

1. O número de valores vazios nesta coluna é superior a 50%?

print(df_categorical.isnull().sum() / df_numerical.shape[0] * 100)

df_categorical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True) #Удаляем, если какая-то колонка 
                                                                          #имеет больше 50% пустых значений

2. Exclua linhas com valores vazios

df_categorical.dropna(inplace=True)#Удаляем строчки с пустыми значениями, 
                                   #если потом останется достаточно данных для обучения

3.1. Inserindo um valor aleatório

import random
df_categorical["колонка"].fillna(lambda x: random.choice(df[df[column] != np.nan]["колонка"]), inplace=True)

3.2. Inserindo um valor constante

from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='constant', fill_value="<Ваше значение здесь>")
df_categorical[["новая_колонка1",'новая_колонка2','новая_колонка3']] = imputer.fit_transform(df_categorical[['колонка1', 'колонка2', 'колонка3']])
df_categorical.drop(labels = ["колонка1","колонка2","колонка3"], axis = 1, inplace = True)

Então, finalmente conseguimos lidar com nulos em dados qualitativos. Agora é hora de realizar a codificação one-hot nos valores que estão em seu banco de dados. Este método é frequentemente usado para garantir que seu algoritmo possa aprender com dados de alta qualidade.

def encode_and_bind(original_dataframe, feature_to_encode):
    dummies = pd.get_dummies(original_dataframe[[feature_to_encode]])
    res = pd.concat([original_dataframe, dummies], axis=1)
    res = res.drop([feature_to_encode], axis=1)
    return(res)

features_to_encode = ["колонка1","колонка2","колонка3"]
for feature in features_to_encode:
    df_categorical = encode_and_bind(df_categorical, feature))

Então, finalmente terminamos de processar dados qualitativos e quantitativos separados - é hora de combiná-los novamente

new_df = pd.concat([df_numerical,df_categorical], axis=1)

Depois de combinarmos os conjuntos de dados em um, podemos finalmente usar a transformação de dados usando MinMaxScaler da biblioteca sklearn. Isso fará com que nossos valores fiquem entre 0 e 1, o que ajudará no futuro treinamento do modelo.

from sklearn.preprocessing import MinMaxScaler
min_max_scaler = MinMaxScaler()
new_df = min_max_scaler.fit_transform(new_df)

Esses dados agora estão prontos para qualquer coisa - redes neurais, algoritmos de ML padrão, etc.!

Neste artigo, não levamos em consideração o trabalho com dados de séries temporais, pois para tais dados você deve usar técnicas de processamento ligeiramente diferentes, dependendo da sua tarefa. No futuro, nossa equipe dedicará um artigo separado a este tema, e esperamos que ele possa trazer algo interessante, novo e útil para sua vida, como este.

Fonte: habr.com

Adicionar um comentário