빠른 데이터 전처리를 위한 메모장-치트 시트

데이터 과학 분야에 입문하는 사람들은 자신을 기다리고 있는 것에 대한 현실적인 기대치가 낮은 경우가 많습니다. 많은 사람들은 이제 멋진 신경망을 작성하거나 Iron Man의 음성 도우미를 만들거나 금융 시장의 모든 사람을 이길 것이라고 생각합니다.
하지만 일 Data 과학자는 데이터 중심적이며 가장 중요하고 시간이 많이 걸리는 측면 중 하나는 데이터를 신경망에 공급하거나 특정 방식으로 분석하기 전에 데이터를 처리하는 것입니다.

이 기사에서 우리 팀은 단계별 지침과 코드를 통해 데이터를 빠르고 쉽게 처리하는 방법을 설명합니다. 우리는 코드를 매우 유연하게 만들고 다양한 데이터 세트에 사용할 수 있도록 노력했습니다.

많은 전문가들은 이 글에서 특별한 것을 발견하지 못할 수도 있지만, 초보자들은 새로운 것을 배울 수 있을 것이고, 빠르고 구조화된 데이터 처리를 위한 별도의 노트북을 만드는 것을 오랫동안 꿈꿔온 사람이라면 누구나 스스로 코드를 복사하고 포맷할 수 있을 것입니다. Github에서 완성된 노트북을 다운로드하세요.

데이터 세트를 받았습니다. 다음에 무엇을할지?

따라서 표준은 다음과 같습니다. 우리가 다루고 있는 내용, 즉 전체적인 그림을 이해해야 합니다. 이를 위해 우리는 팬더를 사용하여 다양한 데이터 유형을 정의합니다.

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

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

빠른 데이터 전처리를 위한 메모장-치트 시트

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

빠른 데이터 전처리를 위한 메모장-치트 시트

열 값을 살펴보겠습니다.

  1. 각 열의 줄 수는 총 줄 수와 일치합니까?
  2. 각 열에 있는 데이터의 본질은 무엇입니까?
  3. 예측을 위해 어떤 열을 타겟팅하고 싶나요?

이러한 질문에 대한 답을 통해 데이터세트를 분석하고 다음 조치에 대한 대략적인 계획을 세울 수 있습니다.

또한 각 열의 값을 더 자세히 살펴보려면 pandas explain() 함수를 사용할 수 있습니다. 하지만 이 함수의 단점은 문자열 값을 갖는 컬럼에 대한 정보를 제공하지 않는다는 점이다. 나중에 다루겠습니다.

df.describe()

빠른 데이터 전처리를 위한 메모장-치트 시트

마법의 시각화

값이 전혀 없는 부분을 살펴보겠습니다.

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

빠른 데이터 전처리를 위한 메모장-치트 시트

이상으로 간략하게 살펴보았습니다. 이제 더 흥미로운 내용으로 넘어가겠습니다.

가능한 경우 모든 행에서 값이 하나만 있는 열을 찾아 제거해 보겠습니다(어떤 방식으로든 결과에 영향을 미치지 않음).

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

이제 우리는 중복 라인(기존 라인 중 하나와 동일한 순서로 동일한 정보를 포함하는 라인)으로부터 우리 자신과 프로젝트의 성공을 보호합니다.

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

우리는 데이터 세트를 두 개로 나눕니다. 하나는 정성적 값이고 다른 하나는 정량적 값입니다.

여기에서 약간의 설명이 필요합니다. 정성적 및 정량적 데이터에서 누락된 데이터가 있는 선이 서로 그다지 상관관계가 없는 경우 무엇을 희생해야 하는지 결정해야 합니다. 즉, 누락된 데이터가 있는 모든 선, 그 중 일부만 또는 특정 열. 선이 서로 연관되어 있으면 데이터 세트를 두 개로 나눌 수 있는 모든 권리가 있습니다. 그렇지 않으면 먼저 누락된 데이터를 정성적, 정량적으로 연관시키지 않는 선을 처리한 다음 데이터 세트를 두 개로 나누어야 합니다.

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

우리는 이 두 가지 유형의 데이터를 더 쉽게 처리할 수 있도록 하기 위해 이렇게 합니다. 나중에 이것이 우리의 삶을 얼마나 더 쉽게 만드는지 이해하게 될 것입니다.

우리는 정량적 데이터를 사용하여 작업합니다.

가장 먼저 해야 할 일은 정량적 데이터에 '스파이 칼럼'이 있는지 확인하는 것이다. 이러한 열은 그 자체로는 정량적 데이터로 표시되지만 정성적 데이터로 작용하기 때문에 이러한 열이라고 부릅니다.

어떻게 식별할 수 있나요? 물론 분석 중인 데이터의 성격에 따라 다르지만 일반적으로 이러한 열에는 고유한 데이터가 거의 없을 수 있습니다(고유 값이 3~10개 정도).

print(df_numerical.nunique())

스파이 칼럼을 식별한 후에는 이를 정량적 데이터에서 정성적 데이터로 이동합니다.

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']) #добавляем третью колонку-шпион в качественные данные

마지막으로, 우리는 정량적 데이터와 정성적 데이터를 완전히 분리했으며 이제 이를 적절하게 사용할 수 있습니다. 첫 번째는 빈 값(NaN, 어떤 경우에는 0이 빈 값으로 허용됨)이 어디에 있는지 이해하는 것입니다.

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

이 시점에서는 XNUMX이 누락된 값을 나타낼 수 있는 열을 이해하는 것이 중요합니다. 이는 데이터 수집 방식 때문입니까? 아니면 데이터 값과 관련이 있을 수 있나요? 이러한 질문은 사례별로 답변해야 합니다.

따라서 XNUMX이 있는 데이터가 누락될 수 있다고 판단되면 나중에 이 손실된 데이터를 더 쉽게 작업할 수 있도록 XNUMX을 NaN으로 바꿔야 합니다.

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

이제 데이터가 누락된 부분을 살펴보겠습니다.

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

빠른 데이터 전처리를 위한 메모장-치트 시트

여기에서 누락된 열 내부의 값은 노란색으로 표시되어야 합니다. 이제 재미가 시작됩니다. 이러한 가치를 어떻게 다룰 것인가? 이러한 값이나 열이 있는 행을 삭제해야 합니까? 아니면 이 빈 값을 다른 값으로 채울까요?

다음은 원칙적으로 빈 값으로 수행할 수 있는 작업을 결정하는 데 도움이 되는 대략적인 다이어그램입니다.

빠른 데이터 전처리를 위한 메모장-치트 시트

0. 불필요한 컬럼을 제거하세요

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

1. 이 열의 빈 값의 개수가 50%보다 큽니까?

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

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

2. 빈 값이 있는 줄 삭제

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

3.1. 임의의 값 삽입

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

3.2. 상수 값 삽입

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. 평균 또는 가장 자주 발생하는 값을 삽입하세요.

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. 다른 모델에서 계산한 값을 삽입하세요.

때로는 sklearn 라이브러리 또는 기타 유사한 라이브러리의 모델을 사용하는 회귀 모델을 사용하여 값을 계산할 수 있습니다. 우리 팀은 가까운 시일 내에 이것이 어떻게 이루어질 수 있는지에 대한 별도의 기사를 작성할 것입니다.

따라서 지금은 정량적 데이터에 대한 설명을 중단하겠습니다. 다양한 작업에 대한 데이터 준비 및 전처리를 더 잘 수행하는 방법에 대한 다른 많은 미묘한 차이가 있고 이 기사에서는 정량적 데이터에 대한 기본 사항을 고려했기 때문입니다. 이제는 정량적 데이터에서 몇 단계 분리된 정성적 데이터로 돌아갈 때입니다. 이 노트북을 원하는 대로 변경하여 다양한 작업에 적용할 수 있으므로 데이터 전처리가 매우 빠르게 진행됩니다!

정성적 데이터

기본적으로 정성적 데이터의 경우 문자열(또는 객체)을 숫자로 포맷팅하기 위해 One-hot-encoding 방식을 사용합니다. 이 지점으로 넘어가기 전에 위의 다이어그램과 코드를 사용하여 빈 값을 처리해 보겠습니다.

df_categorical.nunique()

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

빠른 데이터 전처리를 위한 메모장-치트 시트

0. 불필요한 컬럼을 제거하세요

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

1. 이 열의 빈 값의 개수가 50%보다 큽니까?

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

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

2. 빈 값이 있는 줄 삭제

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

3.1. 임의의 값 삽입

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

3.2. 상수 값 삽입

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)

그래서 우리는 마침내 질적 데이터의 null을 처리할 수 있게 되었습니다. 이제 데이터베이스에 있는 값에 대해 원-핫 인코딩을 수행할 차례입니다. 이 방법은 알고리즘이 고품질 데이터로부터 학습할 수 있는지 확인하는 데 매우 자주 사용됩니다.

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))

이제 별도의 정성적, 정량적 데이터 처리가 드디어 완료되었습니다. 다시 결합할 차례입니다.

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

데이터 세트를 하나로 결합한 후에는 마침내 sklearn 라이브러리의 MinMaxScaler를 사용하여 데이터 변환을 사용할 수 있습니다. 이렇게 하면 값이 0과 1 사이가 되어 향후 모델을 훈련할 때 도움이 됩니다.

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

이제 이 데이터는 신경망, 표준 ML 알고리즘 등 무엇이든 사용할 수 있습니다!

이 기사에서는 시계열 데이터 작업을 고려하지 않았습니다. 이러한 데이터의 경우 작업에 따라 약간 다른 처리 기술을 사용해야 하기 때문입니다. 앞으로 우리 팀은 이 주제에 대해 별도의 기사를 작성할 것이며 이 기사가 여러분의 삶에 이와 같이 흥미롭고 새롭고 유용한 것을 가져올 수 있기를 바랍니다.

출처 : habr.com

코멘트를 추가