Kompleksowe wprowadzenie do obsługi brakujących wartości

Węzeł źródłowy: 1121996

Ten artykuł został opublikowany jako część Blogathon Data Science

Przegląd

Dane dają nam możliwość analizowania i prognozowania wydarzeń przyszłości. Z każdym dniem coraz więcej firm stosuje techniki analizy danych, takie jak prognozowanie predykcyjne, klastrowanie i tak dalej. Choć nauka o złożonych algorytmach ML i DL jest bardzo intrygująca, nie należy zapominać o opanowaniu podstawowych wstępne przetwarzanie danych. Jedną z ważnych części wstępnego przetwarzania danych jest obsługa brakujących wartości. To jest kompletny przewodnik, jak radzić sobie z różnymi rodzajami brakujących danych.

Spis treści

  1. Dlaczego obsługa brakujących wartości jest ważna?
  2. Przyczyny brakujących wartości
  3. Rodzaje brakujących wartości
  4. Sprawdź brakujące wartości w zbiorze danych
  5. Wizualizacja brakujących wartości
  6. Upuszczanie wierszy z brakującymi wartościami
  7. Upuszczanie kolumn z brakującymi wartościami
  8. Imputacja dla zmiennych ciągłych
    1. Imputacja ze średnią
    2. Imputacja z medianą
  9. Przewidywanie brakujących wartości za pomocą regresji
  10. Brakujące wartości w danych kategorycznych
  11. Brakujące wartości w danych szeregów czasowych
    1. Uzupełnij brakujące wartości do przodu
    2. Uzupełnianie wsteczne brakujących wartości
    3. Interpolacja liniowa
  12. Algorytmy odporne na brakujące wartości
  13. Wnioski

Dlaczego ważne jest, aby poradzić sobie z brakującymi danymi?

Dane w świecie rzeczywistym w większości przypadków zawierają wiele brakujących danych. Mogą istnieć różne przyczyny braku każdej wartości. Może dojść do utraty lub uszkodzenia danych lub mogą być też określone przyczyny. Brakujące dane zmniejszą moc predykcyjną Twojego modelu. Jeśli zastosujesz algorytmy z brakującymi danymi, wystąpi błąd w szacowaniu parametrów. Nie możesz być pewny swoich wyników, jeśli nie poradzisz sobie z brakującymi danymi.

Przyczyny brakujących wartości

Czy zastanawiałeś się kiedyś nad przyczynami braku danych w zbiorach danych?

Niektóre z możliwych przyczyn braku danych to:

  • Ludzie nie podają informacji dotyczących niektórych pytań w ankiecie zbierającej dane. Na przykład niektórzy mogą nie czuć się komfortowo, dzieląc się informacjami na temat swoich nawyków zarobkowych, picia i palenia. Są one celowo pomijane przez ludność
  • W niektórych przypadkach dane są gromadzone z różnych dostępnych rekordów z przeszłości, a nie bezpośrednio. W tym przypadku uszkodzenie danych jest poważnym problemem. Ze względu na niskie koszty utrzymania niektóre części danych są uszkodzone, co powoduje brak danych
  • Nieścisłości podczas procesu zbierania danych również przyczyniają się do braku danych. Na przykład przy ręcznym wprowadzaniu danych trudno całkowicie uniknąć błędów ludzkich
  • Niezgodności sprzętu prowadzące do błędnych pomiarów, które z kolei nie mogą być użyte.

Rodzaje brakujących wartości

Brakujące dane mogą wystąpić z różnych przyczyn. Możemy je podzielić na trzy główne grupy: Brakujące całkowicie losowo, Brakujące losowo, Brakujące losowo.

1. Brakujące całkowicie losowo (MCAR)

Brakujące dane nie mają żadnego konkretnego wzoru, są po prostu losowe. Brak tych danych jest niezwiązany lub niezależny od pozostałych zmiennych. Nie jest możliwe przewidzenie tych wartości z resztą danych zmiennych. Na przykład podczas zbierania danych dana próbka zostaje utracona z powodu niedbalstwa. Jest to idealny przypadek, w którym statystycznie analiza nie będzie stronnicza. Ale nie powinieneś zakładać obecności MCAR, chyba że jesteś pewien, ponieważ jest to rzadka sytuacja.

2. Losowe zaginięcie (MAR)

Tutaj, w przeciwieństwie do MCAR, brakuje danych wśród poszczególnych podzbiorów. Za pomocą innych funkcji można przewidzieć, czy dane będą obecne/nieobecne. Ale nie można samemu przewidzieć brakujących danych.

Rozważmy na przykład ankietę dotyczącą czasu spędzanego w Internecie, która zawiera sekcję dotyczącą czasu spędzanego na platformach takich jak Netflix, amazon prime. Obserwuje się, że osoby starsze (powyżej 45 roku życia) rzadziej go wypełniają niż osoby młodsze. To jest przykład MAR. Tutaj parametr „Wiek” decyduje o tym, czy danych będzie brakować, czy nie. MAR występuje bardzo często niż MCAR.

3. Nie zaginął losowo (NMAR)

To poważna i trudna sytuacja. Powiedzmy, że celem ankiety jest zmierzenie nadużywania/uzależnienia od mediów społecznościowych. Jeśli osoby nadmiernie korzystające z mediów społecznościowych nie wypełniają ankiety celowo, to mamy przypadek NMAR. Najprawdopodobniej doprowadzi to do błędu w wynikach. Zwykłe metody, takie jak upuszczanie wierszy/kolumn, imputacja, nie będą działać. Aby to rozwiązać, konieczna byłaby dogłębna znajomość domeny.

Teraz, gdy widzieliśmy różne rodzaje brakujących danych, przejdźmy do różnych sposobów ich obsługi.

Sprawdź brakujące wartości

Kiedy masz zestaw danych, pierwszym krokiem jest sprawdzenie, w których kolumnach brakuje danych i ile. Użyjmy najsłynniejszego zbioru danych wśród nauki o danych, oczywiście, ocalałego z Titanica! Odczytaj zbiór danych za pomocą funkcji pandas read_csv, jak pokazano poniżej.

train=pd.read_csv('../input/titanic/train.csv') test=pd.read_csv('../input/titanic/test.csv') print('Trening data shape: ', train.shape ) print('Testowanie kształtu danych: ', test.shape) train.head()

Dane brakujących wartości

Źródło: Zdjęcie z notatnika autora Kaggle

Teraz mamy ramki danych treningowych i testowych danych tytanicznych.

Jak sprawdzić, w których kolumnach brakuje danych, a ile?

Służy do tego funkcja „isnull()”. Po wywołaniu funkcji sum wraz z parametrem isnull wynikiem jest łączna suma brakujących danych w każdej kolumnie.

missing_values=train.isnull().sum() print(missing_values)
Id pasażera 0 Przeżył 0 Klasa P 0 Imię 0 Płeć 0 Wiek 177 SibSp 0 Parch 0 Bilet 0 Opłata 0 Kabina 687 Zaokrętowany 2 dtype: int64

Zwróć uwagę, że 3 kolumny mają brakujące wartości: Wiek, Kabina, Zaokrętowanie

Chociaż wiemy, ile wartości brakuje w każdej kolumnie, ważne jest, aby znać ich procent w stosunku do wartości całkowitych. Obliczmy to w jednym wierszu kodu.

mis_value_percent = 100 * train.isnull().sum() / len(train) print(mis_value_percent)
Id pasażera 0.000000 Przeżył 0.000000 Klasa P 0.000000 Imię 0.000000 Płeć 0.000000 Wiek 19.865320 SibSp 0.000000 Parch 0.000000 Bilet 0.000000 Opłata za przejazd 0.000000 Kabina 77.104377 Zaokrętowany 0.224467 dtype: float64

Oczywiste jest, że brakuje 77% kolumny „Kabina”, co stanowi bardzo znaczący odsetek. Wiek ma około 19% brakujących danych, a w Embarked brakuje tylko 0.2%. To jest ilościowa analiza brakujących danych, które posiadamy. A co z jakością? Czytaj dalej!

Wizualizacja brakujących wartości za pomocą Missingno

Zgadnij co? Mamy pakiet Pythona specjalnie do wizualizacji i eksploracji brakujących danych w zestawie danych. Pakiet Pythona „Missingno”. Śmiało i zainstaluj go szybko

brak instalacji pip nie

Za jego pomocą możemy tworzyć wizualizacje w postaci map cieplnych, wykresów słupkowych i macierzy. Analizując sposób ich dystrybucji, można stwierdzić, do jakiej kategorii należą MCAR, MAR lub NMAR. Możemy również znaleźć korelację kolumn zawierających brakujące z kolumną docelową

Zacznij od utworzenia wykresu słupkowego dla wartości innych niż null za pomocą funkcji „bar()” biblioteki missingno. Do tej funkcji przekazano ramkę danych pandy.

importuj missingno jako msno msno.bar(train)

braknie | brakujące wartościŹródło: Zdjęcie z notatnika autora Kaggle

Następnie możemy wykreślić wizualizację macierzy. Pomaga nam to dowiedzieć się, w jaki sposób brakujące dane są rozmieszczane w danych, to znaczy czy są zlokalizowane lub równomiernie rozłożone, czy też istnieje jakiś wzorzec i wiele takich pytań.

msno.matrix (pociąg)
pasek wzoru

Na wykresie macierzowym zobaczysz puste wiersze dla wszystkich brakujących danych. Zwróć uwagę, że kolumna „Uruchomiony” zawiera tylko dwa losowe brakujące dane, które nie są zgodne z żadnym wzorcem. Prawdopodobnie zostały utracone podczas pozyskiwania danych. Tak więc można to sklasyfikować jako całkowicie brakujące losowo.

Kolumny Wiek i Kabina mogą być prawdopodobnie MAR. Ale chcemy zapewnić, że nie ma między nimi korelacji.

Jak to zrobić?

Na szczęście dla nas pakiet missingno zapewnia również funkcję „mapy cieplnej”. Korzystając z tego możemy sprawdzić, czy istnieją jakieś korelacje między brakującymi danymi w różnych kolumnach.

msno.mapa cieplna (pociąg)

Wyświetlane są dane wyjściowe!

mapa cieplna | brakująca wartość

Mapa termiczna pokazuje, że nie ma tak silnej korelacji między brakującymi danymi w kolumnie Wiek i Kabina. Tak więc brakujące dane w tych kolumnach można sklasyfikować jako MAR lub Losowe brakujące dane.

Mam nadzieję, że wiesz, jak analizować brakujące wartości. Następnie przejdę do omówienia różnych sposobów postępowania z tymi brakującymi danymi.

Upuszczanie wierszy z brakującymi wartościami

Jest to prosta metoda, w której usuwamy wszystkie wiersze, w których występują braki danych należące do konkretnej kolumny. Tak proste, jak to jest, ma ogromną wadę. Możesz stracić ogromną część swoich danych. Spowoduje to zmniejszenie rozmiaru zestawu danych i spowoduje, że prognozy modelu będą stronnicze. Powinieneś używać tego tylko wtedy, gdy liczba brakujących wartości jest bardzo mniejsza.

Na przykład kolumna „Wprowadzony” zawiera tylko 2 brakujące wartości. Możemy więc upuścić wiersze, w których brakuje tej kolumny. Postępuj zgodnie z poniższym fragmentem kodu.

print('Zbiór danych przed :', len(pociąg)) train.dropna(subset=['Wsiadanie'],how='any',inplace=True) print('Zbiór danych po :', len(pociąg)) print( 'brakujące wartości :',train['Embarked'].isnull().sum())
Zbiór danych przed : 891 Zbiór danych po : 889 braków danych : 0

Wyobraź sobie, że zrobiłeś to samo dla kolumny „Wiek”. Straciłbyś 77% swoich danych!

Upuszczanie kolumn

Gdy w kolumnie występują duże braki danych, nie ma sensu wpisywać wartości z najmniej dostępną liczbą prawdziwych danych, jakie posiadamy. Jeśli więc w którejkolwiek kolumnie brakuje więcej niż 80% wartości, możesz po prostu usunąć tę kolumnę z analizy. W naszym przypadku „Kabina” ma 77% brakujących danych, więc możesz zdecydować się na usunięcie tej kolumny.

Upewnij się, że upuszczona kolumna nie jest kluczowa dla Twojej analizy. Jeśli tak, spróbuj uzyskać więcej danych, a następnie wpisać brakujące wartości.

Imputacja dla zmiennej ciągłej

pociąg['Wiek'][:10]
0 22.0 1 38.0 2 26.0 3 35.0 4 35.0 5 NaN 6 54.0 7 2.0 8 27.0 9 14.0 Imię i nazwisko: Wiek, dtyp: float64
train['Wiek']=train['Wiek'].replace(np.NaN,train['Wiek'].mean()) train['Wiek'][:10]
0 22.000000 1 38.000000 2 26.000000 3 35.000000 4 35.000000 5 29.699118 6 54.000000 7 2.000000 8 27.000000 9 14.000000 Imię: Wiek, dtyp: zmiennoprzecinkowe64

Widać, że 'NaN' zostało zastąpione przez 29.699 (obliczona średnia).

Średnia imputacja ma pewne wady. Jeśli dane mają bardzo nierówny rozkład, z wieloma wartościami odstającymi, średnia nie będzie odzwierciedlać faktycznego rozkładu danych. Na średnią duży wpływ mają wartości ekstremalne lub wartości odstające. Tak więc, jeśli dane nie mają wielu wartości odstających i mają rozkład zbliżony do normalnego, użyj imputacji średniej

Imputacja z medianą

Brakujące wartości funkcji ciągłej można wypełnić medianą pozostałych wartości innych niż null. Zaletą mediany jest to, że wartości odstające nie mają na nią wpływu, w przeciwieństwie do średniej. Zaimplementujmy to tutaj.

train['Wiek']=train['Wiek'].replace(np.NaN,train['Wiek'].median()) train['Wiek'][:10]

imputacja ze średnią

Możesz zauważyć, że mediana (28.0) została wypełniona zamiast wartości NaN.

Podobnie, możesz również wykonać imputację trybu. Ogólnie rzecz biorąc, imputacja w trybie jest popularna w przypadku kategorycznych braków danych. Omówię to szczegółowo w dalszej części

Przewidywanie brakujących wartości za pomocą regresji

Zamiast wypełniać pojedynczą średnią lub medianę we wszystkich miejscach, co jeśli możemy je przewidzieć za pomocą innych zmiennych, które mamy?

Tak! Możemy użyć funkcji z wartościami innymi niż null, aby przewidzieć brakujące wartości. Do przewidywania braków danych można zbudować model regresji lub klasyfikacji. Zaimplementujmy to dla kolumny „Wiek” naszego tytanicznego zbioru danych.

Możemy przetwarzać dane do budowy modelu. Zmienną docelową będzie funkcja „Wiek”.

x_pociąg: Wiersze zbioru danych z obecną wartością „Wiek” są filtrowane. „Wiek” jest celem x_test: Jest to kolumna „Wiek” z wartościami innymi niż null

Połączenia y_pociąg będą posiadały dane, w których brakuje wartości Wiek, które należy przewidzieć (y_pred)

importuj pandy jako pd data=pd.read_csv('../input/titanic/train.csv') data = data[["Ocalony", "Pclass", "Sex", "SibSp", "Parch", "Fare ", "Wiek"]] dane["Płeć"] = [1 if x=="mężczyzna" else 0 dla x w dane["Płeć"]] test_data = dane[dane["Wiek"].isnull()] data.dropna(inplace=True) x_train = data.drop("Wiek", oś=1) x_test = test_data.drop("Wiek", oś=1) y_train = data["Wiek"]

Dopasujmy do tych danych model regresji liniowej. Będę tutaj korzystał z biblioteki sklearn.

from sklearn.linear_model import LinearRegression model = LinearRegression() model.fit(X_train, y_train) y_pred = model.predict(X_test)

Teraz mamy przewidywane wartości null kolumny Age w y_pred.

Wydrukuję kilka przykładów danych wejściowych testowych i przewidywanych wyników dla lepszego zrozumienia.

drukuj(x_test[:10])
Przeżyli Pclass Płeć SibSp Parch Fare 5 0 3 1 0 0 8.4583 17 1 2 1 0 0 13.0000 19 1 3 0 0 0 7.2250 26 0 3 1 0 0 7.2250 28 1 3 0 0 0 7.8792 29 0 3 1 0 0 7.8958 31 1 1 0 1 0 146.5208 32 1 3 0 0 0 7.7500 36 1 3 1 0 0 7.2292 42 0 3 1 0 0 7.8958

W ten sposób dane wejściowe są przekazywane do modelu regresji. Spójrzmy na przewidywane wartości wieku.

drukuj(y_pred[:10])
[29.07080066 30.10833306 22.44685065 29.08927347 22.43705181 29.07922599 32.43692984 22.43898701 22.15615704 29.07922599]

Hurra! Mamy wartości.

Brakujące wartości w danych kategorycznych

Do tej pory widzieliśmy, jak radzić sobie z brakującymi danymi liczbowymi. Co zrobić, jeśli brakuje danych w przypadku cechy kategorycznej? Na przykład funkcja „Kabina” w zestawie danych Titanica jest kategoryczna. Tutaj nie możemy obliczyć średniej i mediany. Możemy więc uzupełnić brakujące wartości trybem lub najczęściej występującą klasą/kategorią.

train['Kabina']=pociąg['Kabina'].fillna(pociąg['Kabina'].value_counts().index[0])

Ta metoda jest preferowana, gdy odsetek braków danych jest mniejszy. Nie powoduje ogromnej utraty danych i jest statystycznie istotna.

Ale jeśli masz dużo brakujących wartości, nie ma sensu imputować najczęściej używanej klasy. Zamiast tego utwórzmy osobną kategorię dla brakujących wartości, takich jak „Nieznane” lub „Niedostępne”. Liczba zajęć zostanie zwiększona o jeden.

Gdy braki danych pochodzą z kolumn kategorialnych (ciągowych lub liczbowych), można je zastąpić najczęściej występującą kategorią. Jeśli liczba brakujących wartości jest bardzo duża, można ją zastąpić nową kategorią.

train['Kabina']=pociąg['Kabina'].fillna('Nieznany') pociąg['Kabina'][:10]

RZĄD KABIN | wypełnij na

Działa dobrze z małym zestawem danych. Neguje również utratę danych, dodając unikalną kategorię.

Jak obsłużyć brakujące wartości w danych szeregów czasowych?

Zestawy danych, w których informacje są gromadzone wraz ze znacznikami czasu w uporządkowany sposób, są oznaczane jako dane szeregów czasowych. Jeśli masz brakujące wartości w danych szeregów czasowych, możesz oczywiście wypróbować dowolną z omówionych powyżej metod. Ale jest też kilka konkretnych metod, które można tutaj zastosować.

Aby uzyskać pomysł, stworzę prosty fikcyjny zbiór danych.

time= pd.date_range("1/01/2021", okresy=10, freq="W") df = pd.DataFrame(indeks=czas); df["Sprzedane jednostki"] = [5.0,4.0,np.nan,np.nan,1.0,np.nan,3.0,6.0,np.nan,2.0]; drukuj(df)

sprzedanych sztuk

Przejdźmy do metod

Uzupełnij brakujące wartości do przodu

Wartość z następnego wiersza zostanie użyta do wypełnienia brakującej wartości. 'ffill' oznacza 'forward fill'. Jest bardzo łatwy do wdrożenia. Musisz tylko przekazać parametr „method” jako „ffill” w funkcji fillna().

forward_filled=df.fillna(method='ffill') print(forward_filled)

wypełnione do przodu

Uzupełnianie wsteczne brakujących wartości

Tutaj używamy wartości z poprzedniego wiersza, aby wypełnić brakującą wartość. „bfill” oznacza wypełnienie wsteczne. Tutaj musisz przekazać „bfill” jako parametr metody.

reverse_filled=df.fillna(method='bfill') print(backward_filled)

wypełniony tyłkiem

Mam nadzieję, że dzięki powyższym zdjęciom zauważysz różnicę w obu przypadkach.

Interpolacja liniowa

Dane szeregów czasowych mają wiele odmian. Powyższe metody imputacji z użyciem backfill i forward fill nie są najlepszym możliwym rozwiązaniem. Interpolacja liniowa na ratunek!

Tutaj wartości są wypełniane wartościami rosnącymi lub malejącymi. Jest to rodzaj techniki imputacji, która próbuje wykreślić liniową zależność między punktami danych. Wykorzystuje dostępne wartości inne niż null do obliczania brakujących punktów.

interpolated=df.interpolate(limit_direction="oba") print(interpolated)

Interpolacja liniowa braków danych

Porównaj te wartości z wypełnianiem wstecz i do przodu i sprawdź sam, co jest dobre!

Oto kilka podstawowych sposobów obsługi braków danych w danych szeregów czasowych

Algorytmy odporne na brakujące wartości

W niektórych przypadkach żadne z powyższych nie działa dobrze. Jednak musisz przeprowadzić analizę. Następnie należy wybrać algorytmy obsługujące brakujące wartości. Jednym z takich algorytmów jest KNN (K najbliższych sąsiadów). Uwzględnia brakujące wartości, biorąc większość z K najbliższych wartości. Las losowy jest również odporny na dane kategoryczne z brakującymi wartościami. Wiele algorytmów opartych na drzewach decyzyjnych, takich jak XGBoost, Catboost, obsługuje dane z brakami danych.

Wnioski

Podsumowując, pierwszym krokiem jest eksploracja danych i sprawdzenie, jakie zmienne mają brakujące dane, jaki jest procent i do jakiej kategorii należy. Po tym będziesz miał strategiczne pojęcie o tym, jakie metody możesz wypróbować. Przydatną wskazówką jest wypróbowanie imputacji z algorytmem najbliższego sąsiada K z wyjątkiem modelu regresji liniowej. Istnieje kilka nowszych metod, które można sprawdzić, na przykład przy użyciu Datawig lub metod imputacji Hot-Deck, jeśli powyższe metody nie działają.

Mam nadzieję, że spodobała Ci się lektura.

Możesz się ze mną skontaktować pod adresem: [email chroniony]

Linkedin: wstępne przetwarzanie danych

Media pokazane w tym artykule nie są własnością Analytics Vidhya i są używane według uznania Autora.

Źródło: https://www.analyticsvidhya.com/blog/2021/10/end-to-end-introduction-to-handling-missing-values/

Znak czasu:

Więcej z Analityka Widhja