{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "rQ8UhzFpgRra" }, "source": [ "# Przygotowanie danych\n", "\n", "[Oryginalne źródło notatnika z *Data Science: Introduction to Machine Learning for Data Science Python and Machine Learning Studio by Lee Stott*](https://github.com/leestott/intro-Datascience/blob/master/Course%20Materials/4-Cleaning_and_Manipulating-Reference.ipynb)\n", "\n", "## Eksplorowanie informacji o `DataFrame`\n", "\n", "> **Cel nauki:** Po zakończeniu tej sekcji powinieneś swobodnie znajdować ogólne informacje o danych przechowywanych w pandas DataFrames.\n", "\n", "Kiedy załadujesz swoje dane do pandas, najprawdopodobniej będą one znajdować się w obiekcie `DataFrame`. Jednak jeśli zbiór danych w Twoim `DataFrame` zawiera 60 000 wierszy i 400 kolumn, jak w ogóle zacząć orientować się, z czym masz do czynienia? Na szczęście pandas oferuje kilka wygodnych narzędzi, które pozwalają szybko uzyskać ogólne informacje o `DataFrame`, a także podejrzeć kilka pierwszych i ostatnich wierszy.\n", "\n", "Aby zbadać tę funkcjonalność, zaimportujemy bibliotekę Python scikit-learn i użyjemy ikonicznego zbioru danych, który każdy data scientist widział setki razy: zbioru danych *Iris* brytyjskiego biologa Ronalda Fishera, użytego w jego pracy z 1936 roku \"The use of multiple measurements in taxonomic problems\":\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true, "id": "hB1RofhdgRrp", "trusted": false }, "outputs": [], "source": [ "import pandas as pd\n", "from sklearn.datasets import load_iris\n", "\n", "iris = load_iris()\n", "iris_df = pd.DataFrame(data=iris['data'], columns=iris['feature_names'])" ] }, { "cell_type": "markdown", "metadata": { "id": "AGA0A_Y8hMdz" }, "source": [ "### `DataFrame.shape`\n", "Załadowaliśmy zbiór danych Iris do zmiennej `iris_df`. Zanim zagłębimy się w dane, warto wiedzieć, ile mamy punktów danych i jaki jest ogólny rozmiar zbioru danych. Dobrze jest przyjrzeć się, z jaką ilością danych mamy do czynienia.\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "LOe5jQohhulf", "outputId": "fb0577ac-3b4a-4623-cb41-20e1b264b3e9" }, "outputs": [ { "data": { "text/plain": [ "(150, 4)" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris_df.shape" ] }, { "cell_type": "markdown", "metadata": { "id": "smE7AGzOhxk2" }, "source": [ "Mamy do czynienia z 150 wierszami i 4 kolumnami danych. Każdy wiersz reprezentuje jeden punkt danych, a każda kolumna odpowiada pojedynczej cesze związanej z ramką danych. Innymi słowy, mamy 150 punktów danych, z których każdy zawiera 4 cechy.\n", "\n", "`shape` tutaj jest atrybutem ramki danych, a nie funkcją, dlatego nie kończy się parą nawiasów.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "d3AZKs0PinGP" }, "source": [ "### `DataFrame.columns`\n", "Przejdźmy teraz do 4 kolumn danych. Co dokładnie każda z nich reprezentuje? Atrybut `columns` pokaże nam nazwy kolumn w dataframe.\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "YPGh_ziji-CY", "outputId": "74e7a43a-77cc-4c80-da56-7f50767c37a0" }, "outputs": [ { "data": { "text/plain": [ "Index(['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)',\n", " 'petal width (cm)'],\n", " dtype='object')" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris_df.columns" ] }, { "cell_type": "markdown", "metadata": { "id": "TsobcU_VjCC_" }, "source": [ "Jak widzimy, są cztery (4) kolumny. Atrybut `columns` informuje nas o nazwach kolumn i w zasadzie o niczym więcej. Ten atrybut nabiera znaczenia, gdy chcemy zidentyfikować cechy zawarte w zbiorze danych.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "2UTlvkjmgRrs" }, "source": [ "### `DataFrame.info`\n", "Ilość danych (podana przez atrybut `shape`) oraz nazwy cech lub kolumn (podane przez atrybut `columns`) dostarczają nam informacji o zbiorze danych. Teraz chcielibyśmy zagłębić się bardziej w ten zbiór danych. Funkcja `DataFrame.info()` jest bardzo przydatna w tym celu.\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "dHHRyG0_gRrt", "outputId": "d8fb0c40-4f18-4e19-da48-c8db77d1d3a5", "trusted": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 150 entries, 0 to 149\n", "Data columns (total 4 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 sepal length (cm) 150 non-null float64\n", " 1 sepal width (cm) 150 non-null float64\n", " 2 petal length (cm) 150 non-null float64\n", " 3 petal width (cm) 150 non-null float64\n", "dtypes: float64(4)\n", "memory usage: 4.8 KB\n" ] } ], "source": [ "iris_df.info()" ] }, { "cell_type": "markdown", "metadata": { "id": "1XgVMpvigRru" }, "source": [ "Z tego miejsca możemy wyciągnąć kilka obserwacji: \n", "1. Typ danych każdej kolumny: W tym zbiorze danych wszystkie dane są przechowywane jako liczby zmiennoprzecinkowe 64-bitowe. \n", "2. Liczba wartości niepustych: Radzenie sobie z brakującymi wartościami to ważny krok w przygotowaniu danych. Zostanie to omówione później w notebooku. \n" ] }, { "cell_type": "markdown", "metadata": { "id": "IYlyxbpWFEF4" }, "source": [ "### DataFrame.describe()\n", "Załóżmy, że mamy dużo danych numerycznych w naszym zbiorze danych. Jednowymiarowe obliczenia statystyczne, takie jak średnia, mediana, kwartyle itp., mogą być wykonane dla każdej kolumny osobno. Funkcja `DataFrame.describe()` dostarcza nam statystyczne podsumowanie numerycznych kolumn w zbiorze danych.\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 297 }, "id": "tWV-CMstFIRA", "outputId": "4fc49941-bc13-4b0c-a412-cb39e7d3f289" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepal length (cm)sepal width (cm)petal length (cm)petal width (cm)
count150.000000150.000000150.000000150.000000
mean5.8433333.0573333.7580001.199333
std0.8280660.4358661.7652980.762238
min4.3000002.0000001.0000000.100000
25%5.1000002.8000001.6000000.300000
50%5.8000003.0000004.3500001.300000
75%6.4000003.3000005.1000001.800000
max7.9000004.4000006.9000002.500000
\n", "
" ], "text/plain": [ " sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)\n", "count 150.000000 150.000000 150.000000 150.000000\n", "mean 5.843333 3.057333 3.758000 1.199333\n", "std 0.828066 0.435866 1.765298 0.762238\n", "min 4.300000 2.000000 1.000000 0.100000\n", "25% 5.100000 2.800000 1.600000 0.300000\n", "50% 5.800000 3.000000 4.350000 1.300000\n", "75% 6.400000 3.300000 5.100000 1.800000\n", "max 7.900000 4.400000 6.900000 2.500000" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris_df.describe()" ] }, { "cell_type": "markdown", "metadata": { "id": "zjjtW5hPGMuM" }, "source": [ "Powyższy wynik pokazuje całkowitą liczbę punktów danych, średnią, odchylenie standardowe, minimum, dolny kwartyl (25%), medianę (50%), górny kwartyl (75%) oraz maksymalną wartość każdej kolumny.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "-lviAu99gRrv" }, "source": [ "### `DataFrame.head`\n", "Dzięki wszystkim powyższym funkcjom i atrybutom uzyskaliśmy ogólny obraz zbioru danych. Wiemy, ile jest punktów danych, ile jest cech, jaki jest typ danych każdej cechy oraz ile wartości niepustych przypada na każdą cechę.\n", "\n", "Teraz nadszedł czas, aby przyjrzeć się samym danym. Zobaczmy, jak wyglądają pierwsze wiersze (pierwsze punkty danych) naszego `DataFrame`:\n" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "DZMJZh0OgRrw", "outputId": "d9393ee5-c106-4797-f815-218f17160e00", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepal length (cm)sepal width (cm)petal length (cm)petal width (cm)
05.13.51.40.2
14.93.01.40.2
24.73.21.30.2
34.63.11.50.2
45.03.61.40.2
\n", "
" ], "text/plain": [ " sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)\n", "0 5.1 3.5 1.4 0.2\n", "1 4.9 3.0 1.4 0.2\n", "2 4.7 3.2 1.3 0.2\n", "3 4.6 3.1 1.5 0.2\n", "4 5.0 3.6 1.4 0.2" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris_df.head()" ] }, { "cell_type": "markdown", "metadata": { "id": "EBHEimZuEFQK" }, "source": [ "W wyniku tutaj widzimy pięć (5) wpisów zestawu danych. Jeśli spojrzymy na indeks po lewej stronie, dowiemy się, że są to pierwsze pięć wierszy.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "oj7GkrTdgRry" }, "source": [ "### Ćwiczenie:\n", "\n", "Na podstawie powyższego przykładu widać, że domyślnie `DataFrame.head` zwraca pierwsze pięć wierszy `DataFrame`. Czy w poniższej komórce kodu potrafisz znaleźć sposób na wyświetlenie więcej niż pięciu wierszy?\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": true, "id": "EKRmRFFegRrz", "trusted": false }, "outputs": [], "source": [ "# Hint: Consult the documentation by using iris_df.head?" ] }, { "cell_type": "markdown", "metadata": { "id": "BJ_cpZqNgRr1" }, "source": [ "### `DataFrame.tail`\n", "Inny sposób przeglądania danych to spojrzenie na ich koniec (zamiast na początek). Odpowiednikiem `DataFrame.head` jest `DataFrame.tail`, który zwraca ostatnie pięć wierszy `DataFrame`:\n" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 0 }, "id": "heanjfGWgRr2", "outputId": "6ae09a21-fe09-4110-b0d7-1a1fbf34d7f3", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepal length (cm)sepal width (cm)petal length (cm)petal width (cm)
1456.73.05.22.3
1466.32.55.01.9
1476.53.05.22.0
1486.23.45.42.3
1495.93.05.11.8
\n", "
" ], "text/plain": [ " sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)\n", "145 6.7 3.0 5.2 2.3\n", "146 6.3 2.5 5.0 1.9\n", "147 6.5 3.0 5.2 2.0\n", "148 6.2 3.4 5.4 2.3\n", "149 5.9 3.0 5.1 1.8" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris_df.tail()" ] }, { "cell_type": "markdown", "metadata": { "id": "31kBWfyLgRr3" }, "source": [ "W praktyce przydatne jest móc łatwo przejrzeć pierwsze kilka wierszy lub ostatnie kilka wierszy `DataFrame`, szczególnie gdy szukasz wartości odstających w uporządkowanych zbiorach danych.\n", "\n", "Wszystkie funkcje i atrybuty pokazane powyżej za pomocą przykładów kodu pomagają nam uzyskać wgląd w dane.\n", "\n", "> **Wniosek:** Nawet samo spojrzenie na metadane dotyczące informacji w `DataFrame` lub na pierwsze i ostatnie kilka wartości pozwala szybko zorientować się w rozmiarze, kształcie i zawartości danych, z którymi pracujesz.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "TvurZyLSDxq_" }, "source": [ "### Brakujące dane\n", "Przyjrzyjmy się brakującym danym. Brakujące dane pojawiają się, gdy w niektórych kolumnach nie ma zapisanej wartości.\n", "\n", "Weźmy przykład: załóżmy, że ktoś jest świadomy swojej wagi i nie wypełnia pola dotyczącego wagi w ankiecie. Wtedy wartość wagi dla tej osoby będzie brakująca.\n", "\n", "W większości przypadków, w rzeczywistych zbiorach danych, występują brakujące wartości.\n", "\n", "**Jak Pandas radzi sobie z brakującymi danymi**\n", "\n", "Pandas obsługuje brakujące wartości na dwa sposoby. Pierwszy z nich widziałeś już wcześniej w poprzednich sekcjach: `NaN`, czyli Not a Number. Jest to w rzeczywistości specjalna wartość będąca częścią specyfikacji IEEE dla liczb zmiennoprzecinkowych i jest używana wyłącznie do wskazywania brakujących wartości zmiennoprzecinkowych.\n", "\n", "W przypadku brakujących wartości innych niż liczby zmiennoprzecinkowe, pandas używa obiektu `None` w Pythonie. Choć może wydawać się to mylące, że spotkasz dwa różne typy wartości oznaczające zasadniczo to samo, istnieją uzasadnione programistyczne powody dla takiego wyboru projektowego. W praktyce takie podejście pozwala pandas na osiągnięcie dobrego kompromisu w zdecydowanej większości przypadków. Niemniej jednak zarówno `None`, jak i `NaN` mają ograniczenia, o których należy pamiętać w kontekście ich użycia.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "lOHqUlZFgRr5" }, "source": [ "### `None`: brakujące dane nie będące liczbami zmiennoprzecinkowymi\n", "Ponieważ `None` pochodzi z Pythona, nie może być używane w tablicach NumPy i pandas, które nie mają typu danych `'object'`. Pamiętaj, że tablice NumPy (oraz struktury danych w pandas) mogą zawierać tylko jeden typ danych. To właśnie daje im ogromną moc w pracy z dużymi zbiorami danych i obliczeniami, ale jednocześnie ogranicza ich elastyczność. Takie tablice muszą być \"podniesione\" do „najniższego wspólnego mianownika”, czyli typu danych, który obejmie wszystko w tablicy. Gdy w tablicy znajduje się `None`, oznacza to, że pracujesz z obiektami Pythona.\n", "\n", "Aby zobaczyć to w praktyce, rozważ poniższą przykładową tablicę (zwróć uwagę na jej `dtype`):\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "QIoNdY4ngRr7", "outputId": "92779f18-62f4-4a03-eca2-e9a101604336", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "array([2, None, 6, 8], dtype=object)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "\n", "example1 = np.array([2, None, 6, 8])\n", "example1" ] }, { "cell_type": "markdown", "metadata": { "id": "pdlgPNbhgRr7" }, "source": [ "Rzeczywistość związana z podnoszeniem typów danych niesie ze sobą dwa skutki uboczne. Po pierwsze, operacje będą wykonywane na poziomie interpretowanego kodu Python, a nie skompilowanego kodu NumPy. W praktyce oznacza to, że wszelkie operacje obejmujące `Series` lub `DataFrames` zawierające `None` będą wolniejsze. Chociaż prawdopodobnie nie zauważysz tego spadku wydajności, w przypadku dużych zbiorów danych może to stać się problemem.\n", "\n", "Drugi skutek uboczny wynika z pierwszego. Ponieważ `None` zasadniczo sprowadza `Series` lub `DataFrame` z powrotem do świata czystego Pythona, użycie agregacji NumPy/pandas, takich jak `sum()` czy `min()` na tablicach zawierających wartość ``None`` zazwyczaj spowoduje błąd:\n" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 292 }, "id": "gWbx-KB9gRr8", "outputId": "ecba710a-22ec-41d5-a39c-11f67e645b50", "trusted": false }, "outputs": [ { "ename": "TypeError", "evalue": "ignored", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mexample1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/numpy/core/_methods.py\u001b[0m in \u001b[0;36m_sum\u001b[0;34m(a, axis, dtype, out, keepdims, initial, where)\u001b[0m\n\u001b[1;32m 45\u001b[0m def _sum(a, axis=None, dtype=None, out=None, keepdims=False,\n\u001b[1;32m 46\u001b[0m initial=_NoValue, where=True):\n\u001b[0;32m---> 47\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mumr_sum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mout\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkeepdims\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minitial\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwhere\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 48\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 49\u001b[0m def _prod(a, axis=None, dtype=None, out=None, keepdims=False,\n", "\u001b[0;31mTypeError\u001b[0m: unsupported operand type(s) for +: 'int' and 'NoneType'" ] } ], "source": [ "example1.sum()" ] }, { "cell_type": "markdown", "metadata": { "id": "LcEwO8UogRr9" }, "source": [ "**Kluczowa informacja**: Dodawanie (i inne operacje) między liczbami całkowitymi a wartościami `None` jest niezdefiniowane, co może ograniczać możliwości pracy z zestawami danych, które je zawierają.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "pWvVHvETgRr9" }, "source": [ "### `NaN`: brakujące wartości zmiennoprzecinkowe\n", "\n", "W przeciwieństwie do `None`, NumPy (a co za tym idzie pandas) obsługuje `NaN` dla swoich szybkich, wektorowych operacji i funkcji uniwersalnych (ufuncs). Złą wiadomością jest to, że każda operacja arytmetyczna wykonana na `NaN` zawsze daje w wyniku `NaN`. Na przykład:\n" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "rcFYfMG9gRr9", "outputId": "699e81b7-5c11-4b46-df1d-06071768690f", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "nan" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.nan + 1" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "BW3zQD2-gRr-", "outputId": "4525b6c4-495d-4f7b-a979-efce1dae9bd0", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "nan" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.nan * 0" ] }, { "cell_type": "markdown", "metadata": { "id": "fU5IPRcCgRr-" }, "source": [ "Dobra wiadomość: agregacje wykonywane na tablicach zawierających `NaN` nie generują błędów. Zła wiadomość: wyniki nie zawsze są użyteczne:\n" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "LCInVgSSgRr_", "outputId": "fa06495a-0930-4867-87c5-6023031ea8b5", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "(nan, nan, nan)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example2 = np.array([2, np.nan, 6, 8]) \n", "example2.sum(), example2.min(), example2.max()" ] }, { "cell_type": "markdown", "metadata": { "id": "nhlnNJT7gRr_" }, "source": [ "### Ćwiczenie:\n" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": true, "id": "yan3QRaOgRr_", "trusted": false }, "outputs": [], "source": [ "# What happens if you add np.nan and None together?\n" ] }, { "cell_type": "markdown", "metadata": { "id": "_iDvIRC8gRsA" }, "source": [] }, { "cell_type": "markdown", "metadata": { "id": "kj6EKdsAgRsA" }, "source": [ "### `NaN` i `None`: wartości null w pandas\n", "\n", "Chociaż `NaN` i `None` mogą zachowywać się nieco inaczej, pandas zostało zaprojektowane tak, aby obsługiwać je zamiennie. Aby zobaczyć, co mamy na myśli, rozważ `Series` liczb całkowitych:\n" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Nji-KGdNgRsA", "outputId": "36aa14d2-8efa-4bfd-c0ed-682991288822", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "0 1\n", "1 2\n", "2 3\n", "dtype: int64" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "int_series = pd.Series([1, 2, 3], dtype=int)\n", "int_series" ] }, { "cell_type": "markdown", "metadata": { "id": "WklCzqb8gRsB" }, "source": [ "### Ćwiczenie:\n" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": true, "id": "Cy-gqX5-gRsB", "trusted": false }, "outputs": [], "source": [ "# Now set an element of int_series equal to None.\n", "# How does that element show up in the Series?\n", "# What is the dtype of the Series?\n" ] }, { "cell_type": "markdown", "metadata": { "id": "WjMQwltNgRsB" }, "source": [ "W procesie podnoszenia typów danych w celu zapewnienia jednorodności danych w `Series` i `DataFrame`, pandas bez problemu zamienia brakujące wartości między `None` a `NaN`. Ze względu na tę cechę projektową, warto myśleć o `None` i `NaN` jako o dwóch różnych odmianach \"wartości pustych\" w pandas. W rzeczywistości, niektóre z podstawowych metod, które będziesz używać do obsługi brakujących wartości w pandas, odzwierciedlają tę ideę w swoich nazwach:\n", "\n", "- `isnull()`: Tworzy maskę logiczną wskazującą brakujące wartości\n", "- `notnull()`: Przeciwieństwo `isnull()`\n", "- `dropna()`: Zwraca przefiltrowaną wersję danych\n", "- `fillna()`: Zwraca kopię danych z uzupełnionymi lub imputowanymi brakującymi wartościami\n", "\n", "Te metody są kluczowe do opanowania i warto się z nimi dobrze zapoznać, więc omówmy je każdą z osobna bardziej szczegółowo.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "Yh5ifd9FgRsB" }, "source": [ "### Wykrywanie wartości null\n", "\n", "Teraz, gdy zrozumieliśmy znaczenie brakujących wartości, musimy je wykryć w naszym zbiorze danych, zanim zaczniemy je obsługiwać. \n", "Zarówno `isnull()`, jak i `notnull()` to podstawowe metody do wykrywania danych null. Obie zwracają maski logiczne dla Twoich danych.\n" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": true, "id": "e-vFp5lvgRsC", "trusted": false }, "outputs": [], "source": [ "example3 = pd.Series([0, np.nan, '', None])" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "1XdaJJ7PgRsC", "outputId": "92fc363a-1874-471f-846d-f4f9ce1f51d0", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "0 False\n", "1 True\n", "2 False\n", "3 True\n", "dtype: bool" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example3.isnull()" ] }, { "cell_type": "markdown", "metadata": { "id": "PaSZ0SQygRsC" }, "source": [ "Przyjrzyj się uważnie wynikowi. Czy coś Cię w nim zaskakuje? Chociaż `0` jest arytmetycznym zerem, to mimo wszystko jest pełnoprawną liczbą całkowitą i pandas traktuje go właśnie w ten sposób. `''` jest nieco bardziej subtelne. Chociaż w Rozdziale 1 używaliśmy go do reprezentowania pustego ciągu znaków, to mimo wszystko jest to obiekt typu string, a nie reprezentacja wartości null w rozumieniu pandas.\n", "\n", "Teraz odwróćmy sytuację i użyjmy tych metod w sposób bardziej zbliżony do praktycznego zastosowania. Możesz używać masek logicznych bezpośrednio jako indeksu ``Series`` lub ``DataFrame``, co może być przydatne, gdy próbujesz pracować z izolowanymi brakującymi (lub obecnymi) wartościami.\n", "\n", "Jeśli chcemy uzyskać całkowitą liczbę brakujących wartości, możemy po prostu wykonać sumowanie maski wygenerowanej przez metodę `isnull()`.\n" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "JCcQVoPkHDUv", "outputId": "001daa72-54f8-4bd5-842a-4df627a79d4d" }, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example3.isnull().sum()" ] }, { "cell_type": "markdown", "metadata": { "id": "PlBqEo3mgRsC" }, "source": [ "### Ćwiczenie:\n" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": true, "id": "ggDVf5uygRsD", "trusted": false }, "outputs": [], "source": [ "# Try running example3[example3.notnull()].\n", "# Before you do so, what do you expect to see?\n" ] }, { "cell_type": "markdown", "metadata": { "id": "D_jWN7mHgRsD" }, "source": [ "**Kluczowa informacja**: Zarówno metody `isnull()`, jak i `notnull()` dają podobne wyniki, gdy używasz ich w DataFrame'ach: pokazują wyniki oraz indeks tych wyników, co będzie ogromną pomocą podczas pracy z danymi.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "BvnoojWsgRr4" }, "source": [ "### Radzenie sobie z brakującymi danymi\n", "\n", "> **Cel nauki:** Po zakończeniu tej sekcji powinieneś wiedzieć, jak i kiedy zastępować lub usuwać brakujące wartości w DataFrames.\n", "\n", "Modele uczenia maszynowego nie potrafią samodzielnie radzić sobie z brakującymi danymi. Dlatego przed przekazaniem danych do modelu musimy zająć się tymi brakującymi wartościami.\n", "\n", "Sposób, w jaki radzimy sobie z brakującymi danymi, wiąże się z subtelnymi kompromisami i może wpłynąć na końcową analizę oraz wyniki w rzeczywistych zastosowaniach.\n", "\n", "Istnieją głównie dwa sposoby radzenia sobie z brakującymi danymi:\n", "\n", "1. Usunięcie wiersza zawierającego brakującą wartość\n", "2. Zastąpienie brakującej wartości inną wartością\n", "\n", "Omówimy obie te metody oraz ich zalety i wady w szczegółach.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "3VaYC1TvgRsD" }, "source": [ "### Usuwanie wartości null\n", "\n", "Ilość danych, które przekazujemy do naszego modelu, ma bezpośredni wpływ na jego wydajność. Usuwanie wartości null oznacza zmniejszenie liczby punktów danych, a co za tym idzie, zmniejszenie rozmiaru zbioru danych. Dlatego zaleca się usuwanie wierszy z wartościami null, gdy zbiór danych jest dość duży.\n", "\n", "Innym przypadkiem może być sytuacja, gdy dany wiersz lub kolumna ma wiele brakujących wartości. W takim przypadku można je usunąć, ponieważ nie wniosą one zbyt wiele do naszej analizy, gdy większość danych dla tego wiersza/kolumny jest nieobecna.\n", "\n", "Oprócz identyfikowania brakujących wartości, pandas oferuje wygodne narzędzie do usuwania wartości null z `Series` i `DataFrame`. Aby zobaczyć to w praktyce, wróćmy do `example3`. Funkcja `DataFrame.dropna()` pomaga w usuwaniu wierszy z wartościami null.\n" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "7uIvS097gRsD", "outputId": "c13fc117-4ca1-4145-a0aa-42ac89e6e218", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "0 0\n", "2 \n", "dtype: object" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example3 = example3.dropna()\n", "example3" ] }, { "cell_type": "markdown", "metadata": { "id": "hil2cr64gRsD" }, "source": [ "Należy zauważyć, że wynik powinien wyglądać jak wynik z `example3[example3.notnull()]`. Różnica polega na tym, że zamiast indeksować na podstawie wartości maskowanych, `dropna` usunął te brakujące wartości z `Series` `example3`.\n", "\n", "Ponieważ DataFrames mają dwa wymiary, oferują więcej opcji usuwania danych.\n" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 142 }, "id": "an-l74sPgRsE", "outputId": "340876a0-63ad-40f6-bd54-6240cdae50ab", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
01.0NaN7
12.05.08
2NaN6.09
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 1.0 NaN 7\n", "1 2.0 5.0 8\n", "2 NaN 6.0 9" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4 = pd.DataFrame([[1, np.nan, 7], \n", " [2, 5, 8], \n", " [np.nan, 6, 9]])\n", "example4" ] }, { "cell_type": "markdown", "metadata": { "id": "66wwdHZrgRsE" }, "source": [ "(Czy zauważyłeś, że pandas przekonwertował dwie kolumny na typ float, aby uwzględnić `NaN`?)\n", "\n", "Nie możesz usunąć pojedynczej wartości z `DataFrame`, więc musisz usunąć całe wiersze lub kolumny. W zależności od tego, co chcesz osiągnąć, możesz wybrać jedną z tych opcji, a pandas daje możliwość wykonania obu. Ponieważ w nauce o danych kolumny zazwyczaj reprezentują zmienne, a wiersze reprezentują obserwacje, częściej usuwa się wiersze danych; domyślne ustawienie dla `dropna()` to usunięcie wszystkich wierszy zawierających jakiekolwiek wartości null:\n" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 80 }, "id": "jAVU24RXgRsE", "outputId": "0b5e5aee-7187-4d3f-b583-a44136ae5f80", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
12.05.08
\n", "
" ], "text/plain": [ " 0 1 2\n", "1 2.0 5.0 8" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4.dropna()" ] }, { "cell_type": "markdown", "metadata": { "id": "TrQRBuTDgRsE" }, "source": [ "Jeśli to konieczne, możesz usunąć wartości NA z kolumn. Użyj `axis=1`, aby to zrobić:\n" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 142 }, "id": "GrBhxu9GgRsE", "outputId": "ff4001f3-2e61-4509-d60e-0093d1068437", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
2
07
18
29
\n", "
" ], "text/plain": [ " 2\n", "0 7\n", "1 8\n", "2 9" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4.dropna(axis='columns')" ] }, { "cell_type": "markdown", "metadata": { "id": "KWXiKTfMgRsF" }, "source": [ "Zauważ, że może to spowodować utratę dużej ilości danych, które mogą być dla Ciebie istotne, szczególnie w przypadku mniejszych zbiorów danych. Co zrobić, jeśli chcesz usunąć tylko te wiersze lub kolumny, które zawierają kilka lub nawet wszystkie wartości null? Możesz określić te ustawienia w `dropna` za pomocą parametrów `how` i `thresh`.\n", "\n", "Domyślnie `how='any'` (jeśli chcesz to sprawdzić samodzielnie lub zobaczyć, jakie inne parametry ma ta metoda, uruchom `example4.dropna?` w komórce kodu). Alternatywnie możesz określić `how='all'`, aby usunąć tylko te wiersze lub kolumny, które zawierają wyłącznie wartości null. Rozszerzmy nasz przykład `DataFrame`, aby zobaczyć to w praktyce w następnym ćwiczeniu.\n" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 142 }, "id": "Bcf_JWTsgRsF", "outputId": "72e0b1b8-52fa-4923-98ce-b6fbed6e44b1", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0123
01.0NaN7NaN
12.05.08NaN
2NaN6.09NaN
\n", "
" ], "text/plain": [ " 0 1 2 3\n", "0 1.0 NaN 7 NaN\n", "1 2.0 5.0 8 NaN\n", "2 NaN 6.0 9 NaN" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4[3] = np.nan\n", "example4" ] }, { "cell_type": "markdown", "metadata": { "id": "pNZer7q9JPNC" }, "source": [ "> Kluczowe informacje: \n", "1. Usuwanie wartości null jest dobrym pomysłem tylko wtedy, gdy zbiór danych jest wystarczająco duży. \n", "2. Całe wiersze lub kolumny można usunąć, jeśli większość ich danych jest brakująca. \n", "3. Metoda `DataFrame.dropna(axis=)` pomaga w usuwaniu wartości null. Argument `axis` określa, czy mają być usunięte wiersze, czy kolumny. \n", "4. Można również użyć argumentu `how`. Domyślnie jest ustawiony na `any`, co oznacza, że usuwane są tylko te wiersze/kolumny, które zawierają jakiekolwiek wartości null. Można go ustawić na `all`, aby określić, że usunięte zostaną tylko te wiersze/kolumny, w których wszystkie wartości są null. \n" ] }, { "cell_type": "markdown", "metadata": { "id": "oXXSfQFHgRsF" }, "source": [ "### Ćwiczenie:\n" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": true, "id": "ExUwQRxpgRsF", "trusted": false }, "outputs": [], "source": [ "# How might you go about dropping just column 3?\n", "# Hint: remember that you will need to supply both the axis parameter and the how parameter.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "38kwAihWgRsG" }, "source": [ "Parametr `thresh` daje bardziej szczegółową kontrolę: ustawiasz liczbę wartości *niepustych*, które wiersz lub kolumna muszą mieć, aby zostały zachowane:\n" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 80 }, "id": "M9dCNMaagRsG", "outputId": "8093713a-54d2-4e54-c73f-4eea315cb6f2", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0123
12.05.08NaN
\n", "
" ], "text/plain": [ " 0 1 2 3\n", "1 2.0 5.0 8 NaN" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4.dropna(axis='rows', thresh=3)" ] }, { "cell_type": "markdown", "metadata": { "id": "fmSFnzZegRsG" }, "source": [ "Tutaj pierwszy i ostatni wiersz zostały usunięte, ponieważ zawierają tylko dwie niepuste wartości.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "mCcxLGyUgRsG" }, "source": [ "### Wypełnianie brakujących wartości\n", "\n", "Czasami warto uzupełnić brakujące wartości takimi, które mogą być uznane za prawidłowe. Istnieje kilka technik wypełniania braków. Pierwszą z nich jest wykorzystanie wiedzy dziedzinowej (znajomości tematu, na którym opiera się zestaw danych), aby w przybliżeniu określić brakujące wartości.\n", "\n", "Możesz użyć `isnull`, aby zrobić to bezpośrednio, ale może to być czasochłonne, szczególnie jeśli masz wiele wartości do uzupełnienia. Ponieważ jest to tak częste zadanie w analizie danych, pandas oferuje funkcję `fillna`, która zwraca kopię `Series` lub `DataFrame` z brakującymi wartościami zastąpionymi wybranymi przez Ciebie. Stwórzmy kolejny przykład `Series`, aby zobaczyć, jak to działa w praktyce.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "CE8S7louLezV" }, "source": [ "### Dane kategoryczne (nienumeryczne)\n", "Najpierw rozważmy dane nienumeryczne. W zbiorach danych mamy kolumny zawierające dane kategoryczne, np. płeć, Prawda lub Fałsz itp.\n", "\n", "W większości takich przypadków zastępujemy brakujące wartości `modą` kolumny. Załóżmy, że mamy 100 punktów danych, z czego 90 wskazało Prawda, 8 wskazało Fałsz, a 2 nie zostały wypełnione. Wtedy możemy uzupełnić te 2 brakujące wartości jako Prawda, biorąc pod uwagę całą kolumnę.\n", "\n", "Tutaj również możemy wykorzystać wiedzę dziedzinową. Rozważmy przykład uzupełniania braków za pomocą mody.\n" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "MY5faq4yLdpQ", "outputId": "19ab472e-1eed-4de8-f8a7-db2a3af3cb1a" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
012True
134None
256False
378True
4910True
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 1 2 True\n", "1 3 4 None\n", "2 5 6 False\n", "3 7 8 True\n", "4 9 10 True" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_mode = pd.DataFrame([[1,2,\"True\"],\n", " [3,4,None],\n", " [5,6,\"False\"],\n", " [7,8,\"True\"],\n", " [9,10,\"True\"]])\n", "\n", "fill_with_mode" ] }, { "cell_type": "markdown", "metadata": { "id": "MLAoMQOfNPlA" }, "source": [] }, { "cell_type": "code", "execution_count": 29, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "WKy-9Y2tN5jv", "outputId": "8da9fa16-e08c-447e-dea1-d4b1db2feebf" }, "outputs": [ { "data": { "text/plain": [ "True 3\n", "False 1\n", "Name: 2, dtype: int64" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_mode[2].value_counts()" ] }, { "cell_type": "markdown", "metadata": { "id": "6iNz_zG_OKrx" }, "source": [] }, { "cell_type": "code", "execution_count": 30, "metadata": { "id": "TxPKteRvNPOs" }, "outputs": [], "source": [ "fill_with_mode[2].fillna('True',inplace=True)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "tvas7c9_OPWE", "outputId": "ec3c8e44-d644-475e-9e22-c65101965850" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
012True
134True
256False
378True
4910True
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 1 2 True\n", "1 3 4 True\n", "2 5 6 False\n", "3 7 8 True\n", "4 9 10 True" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_mode" ] }, { "cell_type": "markdown", "metadata": { "id": "SktitLxxOR16" }, "source": [ "Jak widzimy, wartość null została zastąpiona. Nie trzeba dodawać, że moglibyśmy wpisać cokolwiek zamiast `'True'` i zostałoby to podstawione.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "heYe1I0dOmQ_" }, "source": [ "### Dane Liczbowe\n", "Przechodząc teraz do danych liczbowych. Tutaj mamy dwa powszechne sposoby zastępowania brakujących wartości:\n", "\n", "1. Zastąpienie medianą wiersza \n", "2. Zastąpienie średnią wiersza \n", "\n", "Zastępujemy medianą w przypadku danych skośnych z wartościami odstającymi. Dzieje się tak, ponieważ mediana jest odporna na wartości odstające.\n", "\n", "Gdy dane są znormalizowane, możemy użyć średniej, ponieważ w takim przypadku średnia i mediana będą do siebie bardzo zbliżone.\n", "\n", "Najpierw weźmy kolumnę, która ma rozkład normalny, i uzupełnijmy brakujące wartości średnią tej kolumny.\n" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "09HM_2feOj5Y", "outputId": "7e309013-9acb-411c-9b06-4de795bbeeff" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
0-2.001
1-1.023
2NaN45
31.067
42.089
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 -2.0 0 1\n", "1 -1.0 2 3\n", "2 NaN 4 5\n", "3 1.0 6 7\n", "4 2.0 8 9" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_mean = pd.DataFrame([[-2,0,1],\n", " [-1,2,3],\n", " [np.nan,4,5],\n", " [1,6,7],\n", " [2,8,9]])\n", "\n", "fill_with_mean" ] }, { "cell_type": "markdown", "metadata": { "id": "ka7-wNfzSxbx" }, "source": [ "Średnia kolumny wynosi\n" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "XYtYEf5BSxFL", "outputId": "68a78d18-f0e5-4a9a-a959-2c3676a57c70" }, "outputs": [ { "data": { "text/plain": [ "0.0" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.mean(fill_with_mean[0])" ] }, { "cell_type": "markdown", "metadata": { "id": "oBSRGxKRS39K" }, "source": [] }, { "cell_type": "code", "execution_count": 34, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "FzncQLmuS5jh", "outputId": "00f74fff-01f4-4024-c261-796f50f01d2e" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
0-2.001
1-1.023
20.045
31.067
42.089
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 -2.0 0 1\n", "1 -1.0 2 3\n", "2 0.0 4 5\n", "3 1.0 6 7\n", "4 2.0 8 9" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_mean[0].fillna(np.mean(fill_with_mean[0]),inplace=True)\n", "fill_with_mean" ] }, { "cell_type": "markdown", "metadata": { "id": "CwpVFCrPTC5z" }, "source": [ "Jak widzimy, brakująca wartość została zastąpiona jej średnią.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "jIvF13a1i00Z" }, "source": [ "Teraz spróbujmy innej ramki danych, a tym razem zastąpimy wartości None medianą kolumny.\n" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "DA59Bqo3jBYZ", "outputId": "85dae6ec-7394-4c36-fda0-e04769ec4a32" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
0-20.01
1-12.03
20NaN5
316.07
428.09
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 -2 0.0 1\n", "1 -1 2.0 3\n", "2 0 NaN 5\n", "3 1 6.0 7\n", "4 2 8.0 9" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_median = pd.DataFrame([[-2,0,1],\n", " [-1,2,3],\n", " [0,np.nan,5],\n", " [1,6,7],\n", " [2,8,9]])\n", "\n", "fill_with_median" ] }, { "cell_type": "markdown", "metadata": { "id": "mM1GpXYmjHnc" }, "source": [ "Mediana drugiej kolumny to\n" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "uiDy5v3xjHHX", "outputId": "564b6b74-2004-4486-90d4-b39330a64b88" }, "outputs": [ { "data": { "text/plain": [ "4.0" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_median[1].median()" ] }, { "cell_type": "markdown", "metadata": { "id": "z9PLF75Jj_1s" }, "source": [] }, { "cell_type": "code", "execution_count": 37, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "lFKbOxCMkBbg", "outputId": "a8bd18fb-2765-47d4-e5fe-e965f57ed1f4" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
0-20.01
1-12.03
204.05
316.07
428.09
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 -2 0.0 1\n", "1 -1 2.0 3\n", "2 0 4.0 5\n", "3 1 6.0 7\n", "4 2 8.0 9" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_median[1].fillna(fill_with_median[1].median(),inplace=True)\n", "fill_with_median" ] }, { "cell_type": "markdown", "metadata": { "id": "8JtQ53GSkKWC" }, "source": [ "Jak widzimy, wartość NaN została zastąpiona medianą kolumny\n" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "0ybtWLDdgRsG", "outputId": "b8c238ef-6024-4ee2-be2b-aa1f0fcac61d", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "a 1.0\n", "b NaN\n", "c 2.0\n", "d NaN\n", "e 3.0\n", "dtype: float64" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example5 = pd.Series([1, np.nan, 2, None, 3], index=list('abcde'))\n", "example5" ] }, { "cell_type": "markdown", "metadata": { "id": "yrsigxRggRsH" }, "source": [ "Możesz wypełnić wszystkie puste wpisy jedną wartością, taką jak `0`:\n" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "KXMIPsQdgRsH", "outputId": "aeedfa0a-a421-4c2f-cb0d-183ce8f0c91d", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "a 1.0\n", "b 0.0\n", "c 2.0\n", "d 0.0\n", "e 3.0\n", "dtype: float64" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example5.fillna(0)" ] }, { "cell_type": "markdown", "metadata": { "id": "RRlI5f_hkfKe" }, "source": [ "> Kluczowe wnioski: \n", "1. Uzupełnianie brakujących wartości powinno być przeprowadzane, gdy danych jest niewiele lub istnieje strategia na ich uzupełnienie. \n", "2. Wiedza domenowa może być wykorzystana do przybliżonego uzupełnienia brakujących wartości. \n", "3. W przypadku danych kategorycznych brakujące wartości najczęściej zastępuje się modą kolumny. \n", "4. W przypadku danych numerycznych brakujące wartości zazwyczaj uzupełnia się średnią (dla znormalizowanych zbiorów danych) lub medianą kolumn. \n" ] }, { "cell_type": "markdown", "metadata": { "id": "FI9MmqFJgRsH" }, "source": [ "Ćwiczenie:\n" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": true, "id": "af-ezpXdgRsH", "trusted": false }, "outputs": [], "source": [ "# What happens if you try to fill null values with a string, like ''?\n" ] }, { "cell_type": "markdown", "metadata": { "id": "kq3hw1kLgRsI" }, "source": [ "Możesz **uzupełnić w przód** wartości null, czyli użyć ostatniej prawidłowej wartości do wypełnienia null:\n" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "vO3BuNrggRsI", "outputId": "e2bc591b-0b48-4e88-ee65-754f2737c196", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "a 1.0\n", "b 1.0\n", "c 2.0\n", "d 2.0\n", "e 3.0\n", "dtype: float64" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example5.fillna(method='ffill')" ] }, { "cell_type": "markdown", "metadata": { "id": "nDXeYuHzgRsI" }, "source": [ "Możesz również **uzupełnić wstecz**, aby propagować następną prawidłową wartość wstecz w celu wypełnienia wartości null:\n" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "4M5onHcEgRsI", "outputId": "8f32b185-40dd-4a9f-bd85-54d6b6a414fe", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "a 1.0\n", "b 2.0\n", "c 2.0\n", "d 3.0\n", "e 3.0\n", "dtype: float64" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example5.fillna(method='bfill')" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "id": "MbBzTom5gRsI" }, "source": [ "Jak możesz się domyślić, działa to tak samo z DataFrames, ale możesz również określić `axis`, wzdłuż którego wypełniane będą wartości null:\n" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 142 }, "id": "aRpIvo4ZgRsI", "outputId": "905a980a-a808-4eca-d0ba-224bd7d85955", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0123
01.0NaN7NaN
12.05.08NaN
2NaN6.09NaN
\n", "
" ], "text/plain": [ " 0 1 2 3\n", "0 1.0 NaN 7 NaN\n", "1 2.0 5.0 8 NaN\n", "2 NaN 6.0 9 NaN" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 142 }, "id": "VM1qtACAgRsI", "outputId": "71f2ad28-9b4e-4ff4-f5c3-e731eb489ade", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0123
01.01.07.07.0
12.05.08.08.0
2NaN6.09.09.0
\n", "
" ], "text/plain": [ " 0 1 2 3\n", "0 1.0 1.0 7.0 7.0\n", "1 2.0 5.0 8.0 8.0\n", "2 NaN 6.0 9.0 9.0" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4.fillna(method='ffill', axis=1)" ] }, { "cell_type": "markdown", "metadata": { "id": "ZeMc-I1EgRsI" }, "source": [ "Zauważ, że gdy poprzednia wartość nie jest dostępna do uzupełnienia, wartość null pozostaje.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "eeAoOU0RgRsJ" }, "source": [ "### Ćwiczenie:\n" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "collapsed": true, "id": "e8S-CjW8gRsJ", "trusted": false }, "outputs": [], "source": [ "# What output does example4.fillna(method='bfill', axis=1) produce?\n", "# What about example4.fillna(method='ffill') or example4.fillna(method='bfill')?\n", "# Can you think of a longer code snippet to write that can fill all of the null values in example4?\n" ] }, { "cell_type": "markdown", "metadata": { "id": "YHgy0lIrgRsJ" }, "source": [ "Możesz być kreatywny w używaniu `fillna`. Na przykład, spójrzmy ponownie na `example4`, ale tym razem wypełnijmy brakujące wartości średnią wszystkich wartości w `DataFrame`:\n" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 142 }, "id": "OtYVErEygRsJ", "outputId": "708b1e67-45ca-44bf-a5ee-8b2de09ece73", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0123
01.05.57NaN
12.05.08NaN
21.56.09NaN
\n", "
" ], "text/plain": [ " 0 1 2 3\n", "0 1.0 5.5 7 NaN\n", "1 2.0 5.0 8 NaN\n", "2 1.5 6.0 9 NaN" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4.fillna(example4.mean())" ] }, { "cell_type": "markdown", "metadata": { "id": "zpMvCkLSgRsJ" }, "source": [ "Zauważ, że kolumna 3 nadal nie ma wartości: domyślny kierunek to wypełnianie wartości wierszami.\n", "\n", "> **Wniosek:** Istnieje wiele sposobów radzenia sobie z brakującymi wartościami w zbiorach danych. Konkretna strategia, którą zastosujesz (usuwanie, zastępowanie lub sposób zastępowania), powinna być uzależniona od specyfiki tych danych. Im więcej będziesz pracować z zestawami danych, tym lepiej zrozumiesz, jak radzić sobie z brakującymi wartościami.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "bauDnESIl9FH" }, "source": [ "### Kodowanie danych kategorycznych\n", "\n", "Modele uczenia maszynowego operują wyłącznie na liczbach i wszelkiego rodzaju danych numerycznych. Nie są w stanie rozróżnić \"Tak\" od \"Nie\", ale potrafią odróżnić 0 od 1. Dlatego po uzupełnieniu brakujących wartości musimy zakodować dane kategoryczne w formie numerycznej, aby model mógł je zrozumieć.\n", "\n", "Kodowanie można przeprowadzić na dwa sposoby. Omówimy je w dalszej części.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "uDq9SxB7mu5i" }, "source": [ "**KODOWANIE ETYKIET** \n", "\n", "Kodowanie etykiet polega na zamianie każdej kategorii na liczbę. Na przykład, załóżmy, że mamy zbiór danych pasażerów linii lotniczych i znajduje się w nim kolumna zawierająca ich klasę spośród następujących ['klasa biznesowa', 'klasa ekonomiczna', 'klasa pierwsza']. Jeśli zastosujemy kodowanie etykiet, zostanie to przekształcone na [0,1,2]. Zobaczmy przykład w kodzie. Ponieważ będziemy uczyć się `scikit-learn` w kolejnych notatnikach, tutaj go nie użyjemy.\n" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 235 }, "id": "1vGz7uZyoWHL", "outputId": "9e252855-d193-4103-a54d-028ea7787b34" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
IDclass
010business class
120first class
230economy class
340economy class
450economy class
560business class
\n", "
" ], "text/plain": [ " ID class\n", "0 10 business class\n", "1 20 first class\n", "2 30 economy class\n", "3 40 economy class\n", "4 50 economy class\n", "5 60 business class" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "label = pd.DataFrame([\n", " [10,'business class'],\n", " [20,'first class'],\n", " [30, 'economy class'],\n", " [40, 'economy class'],\n", " [50, 'economy class'],\n", " [60, 'business class']\n", "],columns=['ID','class'])\n", "label" ] }, { "cell_type": "markdown", "metadata": { "id": "IDHnkwTYov-h" }, "source": [ "Aby wykonać kodowanie etykiet na pierwszej kolumnie, musimy najpierw opisać mapowanie każdej klasy na liczbę, zanim zastąpimy\n" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 235 }, "id": "ZC5URJG3o1ES", "outputId": "aab0f1e7-e0f3-4c14-8459-9f9168c85437" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
IDclass
0100
1202
2301
3401
4501
5600
\n", "
" ], "text/plain": [ " ID class\n", "0 10 0\n", "1 20 2\n", "2 30 1\n", "3 40 1\n", "4 50 1\n", "5 60 0" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "class_labels = {'business class':0,'economy class':1,'first class':2}\n", "label['class'] = label['class'].replace(class_labels)\n", "label" ] }, { "cell_type": "markdown", "metadata": { "id": "ftnF-TyapOPt" }, "source": [ "Jak widzimy, wynik jest zgodny z naszymi przewidywaniami. Kiedy więc stosujemy kodowanie etykiet? Kodowanie etykiet stosuje się w jednym lub obu z poniższych przypadków: \n", "1. Gdy liczba kategorii jest duża \n", "2. Gdy kategorie są uporządkowane. \n" ] }, { "cell_type": "markdown", "metadata": { "id": "eQPAPVwsqWT7" }, "source": [ "**JEDNOZNACZNE KODOWANIE (ONE HOT ENCODING)**\n", "\n", "Innym rodzajem kodowania jest jednoznaczne kodowanie (One Hot Encoding). W tym typie kodowania każda kategoria z kolumny zostaje dodana jako osobna kolumna, a każdemu punktowi danych przypisywana jest wartość 0 lub 1 w zależności od tego, czy zawiera daną kategorię. Jeśli więc istnieje n różnych kategorii, do ramki danych zostanie dodanych n kolumn.\n", "\n", "Na przykład, weźmy ten sam przykład klas w samolocie. Kategorie to: ['business class', 'economy class', 'first class']. Jeśli zastosujemy jednoznaczne kodowanie, do zbioru danych zostaną dodane następujące trzy kolumny: ['class_business class', 'class_economy class', 'class_first class'].\n" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 235 }, "id": "ZM0eVh0ArKUL", "outputId": "83238a76-b3a5-418d-c0b6-605b02b6891b" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
IDclass
010business class
120first class
230economy class
340economy class
450economy class
560business class
\n", "
" ], "text/plain": [ " ID class\n", "0 10 business class\n", "1 20 first class\n", "2 30 economy class\n", "3 40 economy class\n", "4 50 economy class\n", "5 60 business class" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "one_hot = pd.DataFrame([\n", " [10,'business class'],\n", " [20,'first class'],\n", " [30, 'economy class'],\n", " [40, 'economy class'],\n", " [50, 'economy class'],\n", " [60, 'business class']\n", "],columns=['ID','class'])\n", "one_hot" ] }, { "cell_type": "markdown", "metadata": { "id": "aVnZ7paDrWmb" }, "source": [ "Wykonajmy one hot encoding na pierwszej kolumnie\n" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "id": "RUPxf7egrYKr" }, "outputs": [], "source": [ "one_hot_data = pd.get_dummies(one_hot,columns=['class'])" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 235 }, "id": "TM37pHsFr4ge", "outputId": "7be15f53-79b2-447a-979c-822658339a9e" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
IDclass_business classclass_economy classclass_first class
010100
120001
230010
340010
450010
560100
\n", "
" ], "text/plain": [ " ID class_business class class_economy class class_first class\n", "0 10 1 0 0\n", "1 20 0 0 1\n", "2 30 0 1 0\n", "3 40 0 1 0\n", "4 50 0 1 0\n", "5 60 1 0 0" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "one_hot_data" ] }, { "cell_type": "markdown", "metadata": { "id": "_zXRLOjXujdA" }, "source": [ "Każda zakodowana kolumna one-hot zawiera 0 lub 1, co określa, czy dana kategoria istnieje dla tego punktu danych.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "bDnC4NQOu0qr" }, "source": [ "Kiedy używamy kodowania one hot? Kodowanie one hot stosuje się w jednym lub obu z poniższych przypadków:\n", "\n", "1. Gdy liczba kategorii i rozmiar zbioru danych są niewielkie.\n", "2. Gdy kategorie nie mają określonego porządku.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "XnUmci_4uvyu" }, "source": [ "> Kluczowe wnioski: \n", "1. Kodowanie służy do przekształcania danych nienumerycznych na dane numeryczne. \n", "2. Istnieją dwa rodzaje kodowania: kodowanie etykiet (Label encoding) i kodowanie One Hot, które można zastosować w zależności od wymagań zbioru danych. \n" ] }, { "cell_type": "markdown", "metadata": { "id": "K8UXOJYRgRsJ" }, "source": [ "## Usuwanie zduplikowanych danych\n", "\n", "> **Cel nauki:** Po zakończeniu tej sekcji powinieneś swobodnie identyfikować i usuwać zduplikowane wartości z DataFrames.\n", "\n", "Oprócz brakujących danych, w rzeczywistych zbiorach danych często napotkasz zduplikowane dane. Na szczęście pandas oferuje prosty sposób na wykrywanie i usuwanie zduplikowanych wpisów.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "qrEG-Wa0gRsJ" }, "source": [ "### Identyfikacja duplikatów: `duplicated`\n", "\n", "Możesz łatwo zidentyfikować duplikaty za pomocą metody `duplicated` w pandas. Zwraca ona maskę logiczną wskazującą, czy dany wpis w `DataFrame` jest duplikatem wcześniejszego. Stwórzmy kolejny przykład `DataFrame`, aby zobaczyć, jak to działa w praktyce.\n" ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "ZLu6FEnZgRsJ", "outputId": "376512d1-d842-4db1-aea3-71052aeeecaf", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lettersnumbers
0A1
1B2
2A1
3B3
4B3
\n", "
" ], "text/plain": [ " letters numbers\n", "0 A 1\n", "1 B 2\n", "2 A 1\n", "3 B 3\n", "4 B 3" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example6 = pd.DataFrame({'letters': ['A','B'] * 2 + ['B'],\n", " 'numbers': [1, 2, 1, 3, 3]})\n", "example6" ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "cIduB5oBgRsK", "outputId": "3da27b3d-4d69-4e1d-bb52-0af21bae87f2", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "0 False\n", "1 False\n", "2 True\n", "3 False\n", "4 True\n", "dtype: bool" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example6.duplicated()" ] }, { "cell_type": "markdown", "metadata": { "id": "0eDRJD4SgRsK" }, "source": [ "### Usuwanie duplikatów: `drop_duplicates`\n", "`drop_duplicates` po prostu zwraca kopię danych, dla których wszystkie wartości oznaczone jako `duplicated` są `False`:\n" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 142 }, "id": "w_YPpqIqgRsK", "outputId": "ac66bd2f-8671-4744-87f5-8b8d96553dea", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lettersnumbers
0A1
1B2
3B3
\n", "
" ], "text/plain": [ " letters numbers\n", "0 A 1\n", "1 B 2\n", "3 B 3" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example6.drop_duplicates()" ] }, { "cell_type": "markdown", "metadata": { "id": "69AqoCZAgRsK" }, "source": [ "Zarówno `duplicated`, jak i `drop_duplicates` domyślnie uwzględniają wszystkie kolumny, ale możesz określić, że mają sprawdzać tylko podzbiór kolumn w Twoim `DataFrame`:\n" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 111 }, "id": "BILjDs67gRsK", "outputId": "ef6dcc08-db8b-4352-c44e-5aa9e2bec0d3", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lettersnumbers
0A1
1B2
\n", "
" ], "text/plain": [ " letters numbers\n", "0 A 1\n", "1 B 2" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example6.drop_duplicates(['letters'])" ] }, { "cell_type": "markdown", "metadata": { "id": "GvX4og1EgRsL" }, "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**Zastrzeżenie**: \nTen dokument został przetłumaczony za pomocą usługi tłumaczeniowej AI [Co-op Translator](https://github.com/Azure/co-op-translator). Chociaż dokładamy wszelkich starań, aby tłumaczenie było precyzyjne, prosimy pamiętać, że automatyczne tłumaczenia mogą zawierać błędy lub nieścisłości. Oryginalny dokument w jego rodzimym języku powinien być uznawany za wiarygodne źródło. W przypadku informacji krytycznych zaleca się skorzystanie z profesjonalnego tłumaczenia wykonanego przez człowieka. Nie ponosimy odpowiedzialności za jakiekolwiek nieporozumienia lub błędne interpretacje wynikające z korzystania z tego tłumaczenia.\n" ] } ], "metadata": { "anaconda-cloud": {}, "colab": { "name": "notebook.ipynb", "provenance": [] }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.4" }, "coopTranslator": { "original_hash": "8533b3a2230311943339963fc7f04c21", "translation_date": "2025-09-02T07:36:21+00:00", "source_file": "2-Working-With-Data/08-data-preparation/notebook.ipynb", "language_code": "pl" } }, "nbformat": 4, "nbformat_minor": 0 }