Notebook-Spickzettel für eine schnelle Datenvorverarbeitung

Menschen, die in den Bereich Data Science einsteigen, haben oft weniger realistische Erwartungen an das, was sie erwartet. Viele Leute denken, dass sie jetzt coole neuronale Netze schreiben, einen Sprachassistenten von Iron Man erstellen oder alle auf den Finanzmärkten schlagen werden.
Aber Arbeit Datum Wissenschaftler sind datengesteuert und einer der wichtigsten und zeitaufwändigsten Aspekte ist die Verarbeitung der Daten, bevor sie in ein neuronales Netzwerk eingespeist oder auf eine bestimmte Weise analysiert werden.

In diesem Artikel beschreibt unser Team mit Schritt-für-Schritt-Anleitungen und Code, wie Sie Daten schnell und einfach verarbeiten können. Wir haben versucht, den Code sehr flexibel zu gestalten und ihn für verschiedene Datensätze verwenden zu können.

Viele Profis werden in diesem Artikel vielleicht nichts Außergewöhnliches finden, aber Anfänger können etwas Neues lernen, und jeder, der schon lange davon geträumt hat, ein separates Notizbuch für die schnelle und strukturierte Datenverarbeitung zu erstellen, kann den Code kopieren und für sich selbst formatieren, oder Laden Sie das fertige Notebook von Github herunter.

Wir haben den Datensatz erhalten. Was macht man als nächstes?

Der Maßstab also: Wir müssen verstehen, womit wir es zu tun haben, das Gesamtbild. Dazu verwenden wir Pandas, um einfach verschiedene Datentypen zu definieren.

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

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

Notebook-Spickzettel für eine schnelle Datenvorverarbeitung

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

Notebook-Spickzettel für eine schnelle Datenvorverarbeitung

Schauen wir uns die Spaltenwerte an:

  1. Entspricht die Anzahl der Zeilen in jeder Spalte der Gesamtanzahl der Zeilen?
  2. Was ist der Kern der Daten in jeder Spalte?
  3. Auf welche Spalte möchten wir abzielen, um Vorhersagen dafür zu treffen?

Die Antworten auf diese Fragen ermöglichen es Ihnen, den Datensatz zu analysieren und grob einen Plan für Ihre nächsten Aktionen zu erstellen.

Für einen tieferen Blick auf die Werte in jeder Spalte können wir außerdem die Pandas-beschreiben()-Funktion verwenden. Der Nachteil dieser Funktion besteht jedoch darin, dass sie keine Informationen über Spalten mit String-Werten liefert. Wir kümmern uns später um sie.

df.describe()

Notebook-Spickzettel für eine schnelle Datenvorverarbeitung

Magische Visualisierung

Schauen wir uns an, wo wir überhaupt keine Werte haben:

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

Notebook-Spickzettel für eine schnelle Datenvorverarbeitung

Das war ein kurzer Blick von oben, jetzt kommen wir zu interessanteren Dingen

Versuchen wir, Spalten zu finden und wenn möglich zu entfernen, die in allen Zeilen nur einen Wert haben (sie haben keinen Einfluss auf das Ergebnis):

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

Jetzt schützen wir uns und den Erfolg unseres Projekts vor doppelten Zeilen (Zeilen, die dieselben Informationen in derselben Reihenfolge enthalten wie eine der vorhandenen Zeilen):

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

Wir teilen den Datensatz in zwei Teile auf: einen mit qualitativen Werten und einen mit quantitativen Werten

Hier müssen wir eine kleine Klarstellung vornehmen: Wenn die Zeilen mit fehlenden Daten in qualitativen und quantitativen Daten nicht sehr stark miteinander korrelieren, müssen wir entscheiden, was wir opfern – alle Zeilen mit fehlenden Daten, nur einen Teil davon. oder bestimmte Spalten. Wenn die Linien korreliert sind, haben wir das Recht, den Datensatz in zwei Teile zu teilen. Andernfalls müssen Sie sich zunächst mit den Zeilen befassen, die die fehlenden Daten qualitativ und quantitativ nicht korrelieren, und erst dann den Datensatz in zwei Teile teilen.

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

Wir tun dies, um die Verarbeitung dieser beiden unterschiedlichen Datentypen zu erleichtern – später werden wir verstehen, wie viel einfacher dies unser Leben macht.

Wir arbeiten mit quantitativen Daten

Als Erstes sollten wir feststellen, ob die quantitativen Daten „Spionagespalten“ enthalten. Wir nennen diese Spalten so, weil sie sich als quantitative Daten darstellen, aber als qualitative Daten fungieren.

Wie definieren wir sie? Natürlich hängt alles von der Art der Daten ab, die Sie analysieren, aber im Allgemeinen enthalten solche Spalten möglicherweise nur wenige eindeutige Daten (im Bereich von 3–10 eindeutigen Werten).

print(df_numerical.nunique())

Sobald wir die Spionagespalten identifiziert haben, werden wir sie von quantitativen Daten zu qualitativen Daten verschieben:

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

Endlich haben wir quantitative Daten vollständig von qualitativen Daten getrennt und können nun richtig damit arbeiten. Das erste, was wir tun müssen, ist zu verstehen, wo wir leere Werte haben (NaN, und in einigen Fällen wird 0 als leerer Wert akzeptiert).

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

An dieser Stelle ist es wichtig zu verstehen, in welchen Spalten Nullen auf fehlende Werte hinweisen können: Liegt das daran, wie die Daten erfasst wurden? Oder könnte es mit den Datenwerten zusammenhängen? Diese Fragen müssen im Einzelfall beantwortet werden.

Wenn wir also immer noch zu dem Schluss kommen, dass uns an Stellen mit Nullen möglicherweise Daten fehlen, sollten wir die Nullen durch NaN ersetzen, um die spätere Arbeit mit diesen verlorenen Daten zu erleichtern:

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

Sehen wir uns nun an, wo uns Daten fehlen:

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

Notebook-Spickzettel für eine schnelle Datenvorverarbeitung

Hier sollten die fehlenden Werte innerhalb der Spalten gelb markiert werden. Und jetzt beginnt der Spaß – wie geht man mit diesen Werten um? Soll ich Zeilen mit diesen Werten oder Spalten löschen? Oder diese leeren Werte mit anderen füllen?

Hier ist ein ungefähres Diagramm, das Ihnen bei der Entscheidung helfen kann, was im Prinzip mit leeren Werten gemacht werden kann:

Notebook-Spickzettel für eine schnelle Datenvorverarbeitung

0. Entfernen Sie unnötige Spalten

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

1. Ist die Anzahl der leeren Werte in dieser Spalte größer als 50 %?

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

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

2. Zeilen mit leeren Werten löschen

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

3.1. Einen Zufallswert einfügen

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

3.2. Einen konstanten Wert einfügen

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. Geben Sie den durchschnittlichen oder häufigsten Wert ein

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. Geben Sie den von einem anderen Modell berechneten Wert ein

Manchmal können Werte mithilfe von Regressionsmodellen unter Verwendung von Modellen aus der Sklearn-Bibliothek oder anderen ähnlichen Bibliotheken berechnet werden. Unser Team wird in naher Zukunft einen separaten Artikel darüber schreiben, wie dies bewerkstelligt werden kann.

Daher wird die Erzählung über quantitative Daten vorerst unterbrochen, da es viele andere Nuancen darüber gibt, wie die Datenaufbereitung und -vorverarbeitung für verschiedene Aufgaben besser durchgeführt werden kann, und die grundlegenden Dinge für quantitative Daten in diesem Artikel berücksichtigt wurden Jetzt ist es an der Zeit, zu den qualitativen Daten zurückzukehren, die wir einige Schritte zurück von den quantitativen Daten getrennt haben. Sie können dieses Notizbuch nach Belieben verändern und an unterschiedliche Aufgaben anpassen, sodass die Datenvorverarbeitung sehr schnell vonstatten geht!

Qualitative Daten

Grundsätzlich wird für qualitative Daten die One-Hot-Encoding-Methode verwendet, um sie von einer Zeichenfolge (oder einem Objekt) in eine Zahl zu formatieren. Bevor wir zu diesem Punkt übergehen, verwenden wir das obige Diagramm und den Code, um mit leeren Werten umzugehen.

df_categorical.nunique()

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

Notebook-Spickzettel für eine schnelle Datenvorverarbeitung

0. Entfernen Sie unnötige Spalten

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

1. Ist die Anzahl der leeren Werte in dieser Spalte größer als 50 %?

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

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

2. Zeilen mit leeren Werten löschen

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

3.1. Einen Zufallswert einfügen

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

3.2. Einen konstanten Wert einfügen

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)

Damit haben wir endlich die Nullwerte in qualitativen Daten im Griff. Jetzt ist es an der Zeit, eine One-Hot-Codierung für die Werte in Ihrer Datenbank durchzuführen. Diese Methode wird sehr häufig verwendet, um sicherzustellen, dass Ihr Algorithmus aus hochwertigen Daten lernen kann.

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

Wir haben also endlich die Verarbeitung getrennter qualitativer und quantitativer Daten abgeschlossen – es ist Zeit, sie wieder zu kombinieren

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

Nachdem wir die Datensätze zu einem zusammengefasst haben, können wir endlich die Datentransformation mit MinMaxScaler aus der sklearn-Bibliothek verwenden. Dadurch liegen unsere Werte zwischen 0 und 1, was beim zukünftigen Training des Modells hilfreich sein wird.

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

Diese Daten sind jetzt für alles bereit – neuronale Netze, Standard-ML-Algorithmen usw.!

In diesem Artikel haben wir die Arbeit mit Zeitreihendaten nicht berücksichtigt, da Sie für solche Daten je nach Aufgabenstellung leicht unterschiedliche Verarbeitungstechniken verwenden sollten. In Zukunft wird unser Team diesem Thema einen eigenen Artikel widmen und wir hoffen, dass wir dadurch etwas Interessantes, Neues und Nützliches in Ihr Leben bringen können, genau wie diesen.

Source: habr.com

Kommentar hinzufügen