You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4240 lines
124 KiB
4240 lines
124 KiB
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "rQ8UhzFpgRra"
|
|
},
|
|
"source": [
|
|
"# Przygotowanie danych\n",
|
|
"\n",
|
|
"[Oryginalne źródło notebooka z *Data Science: Introduction to Machine Learning for Data Science Python and Machine Learning Studio autorstwa Lee Stott*](https://github.com/leestott/intro-Datascience/blob/master/Course%20Materials/4-Cleaning_and_Manipulating-Reference.ipynb)\n",
|
|
"\n",
|
|
"## Eksploracja informacji o `DataFrame`\n",
|
|
"\n",
|
|
"> **Cel nauki:** Po zakończeniu tej części powinieneś swobodnie znajdować ogólne informacje o danych przechowywanych w pandas DataFrames.\n",
|
|
"\n",
|
|
"Gdy załadujesz swoje dane do pandas, najprawdopodobniej będą one w formacie `DataFrame`. Jednak jeśli zestaw danych w Twoim `DataFrame` zawiera 60 000 wierszy i 400 kolumn, od czego zacząć, aby zrozumieć, z czym pracujesz? Na szczęście pandas oferuje kilka wygodnych narzędzi, które pozwalają szybko uzyskać ogólne informacje o `DataFrame`, a także zobaczyć kilka pierwszych i ostatnich wierszy.\n",
|
|
"\n",
|
|
"Aby zbadać tę funkcjonalność, zaimportujemy bibliotekę Python scikit-learn i użyjemy ikonicznego zestawu danych, który każdy data scientist widział setki razy: zestawu 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 punktów danych posiadamy oraz jaki jest ogólny rozmiar zbioru danych. Przydatne jest spojrzenie na ilość danych, z którymi 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. Czyli zasadniczo 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` pozwoli nam uzyskać 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`) mówią nam coś o zestawie danych. Teraz chcielibyśmy zagłębić się bardziej w zestaw 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": [
|
|
"<class 'pandas.core.frame.DataFrame'>\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": [
|
|
"Na podstawie tego możemy poczynić kilka obserwacji:\n",
|
|
"1. Typ danych każdej kolumny: W tym zbiorze danych wszystkie dane są przechowywane jako 64-bitowe liczby zmiennoprzecinkowe.\n",
|
|
"2. Liczba wartości niepustych: Radzenie sobie z wartościami pustymi to ważny krok w przygotowaniu danych. Zostanie to omówione później w notatniku.\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ć wykonywane na każdej kolumnie 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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>sepal length (cm)</th>\n",
|
|
" <th>sepal width (cm)</th>\n",
|
|
" <th>petal length (cm)</th>\n",
|
|
" <th>petal width (cm)</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>count</th>\n",
|
|
" <td>150.000000</td>\n",
|
|
" <td>150.000000</td>\n",
|
|
" <td>150.000000</td>\n",
|
|
" <td>150.000000</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>mean</th>\n",
|
|
" <td>5.843333</td>\n",
|
|
" <td>3.057333</td>\n",
|
|
" <td>3.758000</td>\n",
|
|
" <td>1.199333</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>std</th>\n",
|
|
" <td>0.828066</td>\n",
|
|
" <td>0.435866</td>\n",
|
|
" <td>1.765298</td>\n",
|
|
" <td>0.762238</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>min</th>\n",
|
|
" <td>4.300000</td>\n",
|
|
" <td>2.000000</td>\n",
|
|
" <td>1.000000</td>\n",
|
|
" <td>0.100000</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>25%</th>\n",
|
|
" <td>5.100000</td>\n",
|
|
" <td>2.800000</td>\n",
|
|
" <td>1.600000</td>\n",
|
|
" <td>0.300000</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>50%</th>\n",
|
|
" <td>5.800000</td>\n",
|
|
" <td>3.000000</td>\n",
|
|
" <td>4.350000</td>\n",
|
|
" <td>1.300000</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>75%</th>\n",
|
|
" <td>6.400000</td>\n",
|
|
" <td>3.300000</td>\n",
|
|
" <td>5.100000</td>\n",
|
|
" <td>1.800000</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>max</th>\n",
|
|
" <td>7.900000</td>\n",
|
|
" <td>4.400000</td>\n",
|
|
" <td>6.900000</td>\n",
|
|
" <td>2.500000</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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 zestawu 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 czas przyjrzeć się samym danym. Zobaczmy, jak wyglądają pierwsze kilka wierszy (pierwsze kilka punktów 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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>sepal length (cm)</th>\n",
|
|
" <th>sepal width (cm)</th>\n",
|
|
" <th>petal length (cm)</th>\n",
|
|
" <th>petal width (cm)</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>5.1</td>\n",
|
|
" <td>3.5</td>\n",
|
|
" <td>1.4</td>\n",
|
|
" <td>0.2</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>4.9</td>\n",
|
|
" <td>3.0</td>\n",
|
|
" <td>1.4</td>\n",
|
|
" <td>0.2</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>4.7</td>\n",
|
|
" <td>3.2</td>\n",
|
|
" <td>1.3</td>\n",
|
|
" <td>0.2</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>4.6</td>\n",
|
|
" <td>3.1</td>\n",
|
|
" <td>1.5</td>\n",
|
|
" <td>0.2</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>4</th>\n",
|
|
" <td>5.0</td>\n",
|
|
" <td>3.6</td>\n",
|
|
" <td>1.4</td>\n",
|
|
" <td>0.2</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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": [
|
|
"Na podstawie wyników tutaj widzimy pięć (5) wpisów w zestawie danych. Jeśli spojrzymy na indeks po lewej stronie, dowiadujemy 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",
|
|
"Innym sposobem przeglądania danych może być spojrzenie od końca (zamiast od początku). 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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>sepal length (cm)</th>\n",
|
|
" <th>sepal width (cm)</th>\n",
|
|
" <th>petal length (cm)</th>\n",
|
|
" <th>petal width (cm)</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>145</th>\n",
|
|
" <td>6.7</td>\n",
|
|
" <td>3.0</td>\n",
|
|
" <td>5.2</td>\n",
|
|
" <td>2.3</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>146</th>\n",
|
|
" <td>6.3</td>\n",
|
|
" <td>2.5</td>\n",
|
|
" <td>5.0</td>\n",
|
|
" <td>1.9</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>147</th>\n",
|
|
" <td>6.5</td>\n",
|
|
" <td>3.0</td>\n",
|
|
" <td>5.2</td>\n",
|
|
" <td>2.0</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>148</th>\n",
|
|
" <td>6.2</td>\n",
|
|
" <td>3.4</td>\n",
|
|
" <td>5.4</td>\n",
|
|
" <td>2.3</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>149</th>\n",
|
|
" <td>5.9</td>\n",
|
|
" <td>3.0</td>\n",
|
|
" <td>5.1</td>\n",
|
|
" <td>1.8</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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 łatwe przeglądanie pierwszych kilku wierszy lub ostatnich kilku 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 jest zapisane żadne 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 brakować.\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 sposób, który widziałeś wcześniej w poprzednich sekcjach, to `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` z Pythona. Chociaż może wydawać się to mylące, że spotkasz dwa różne rodzaje 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 zwykłego 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<ipython-input-10-ce9901ad18bd>\u001b[0m in \u001b[0;36m<module>\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 uwaga**: 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` w swoich szybkich, wektorowych operacjach i funkcjach ufunc. Zła wiadomość jest taka, że każda operacja arytmetyczna wykonana na `NaN` zawsze daje wynik `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 uruchamiane na tablicach zawierających `NaN` nie generują błędów. Zła wiadomość: wyniki nie są jednolicie 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": [
|
|
"Pamiętaj: `NaN` jest tylko dla brakujących wartości zmiennoprzecinkowych; nie ma odpowiednika `NaN` dla liczb całkowitych, ciągów znaków ani wartości logicznych.\n"
|
|
]
|
|
},
|
|
{
|
|
"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ć, o co chodzi, 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": [
|
|
"Podczas procesu podnoszenia typów danych w celu zapewnienia jednolitoś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 \"null\" 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",
|
|
"To są kluczowe metody, które warto opanować i dobrze zrozumieć, więc omówmy je 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ć. Zarówno `isnull()`, jak i `notnull()` są podstawowymi metodami 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 wynikom. Czy coś Cię zaskakuje? Chociaż `0` jest arytmetycznym zerem, to wciąż jest pełnoprawną liczbą całkowitą i pandas traktuje go właśnie w ten sposób. `''` jest nieco bardziej subtelne. Chociaż używaliśmy tego w Sekcji 1 do reprezentowania pustej wartości tekstowej, to nadal jest to obiekt typu string, a nie reprezentacja 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ć sumę na masce 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 niezwykle pomocne 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 radzenia sobie z brakującymi danymi wiąże się z subtelnymi kompromisami, które mogą wpłynąć na ostateczną analizę i 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, że zmniejszamy liczbę punktów danych, a tym samym rozmiar 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 określony wiersz lub kolumna ma wiele brakujących wartości. Wtedy można je usunąć, ponieważ nie wniosą one dużej wartości do naszej analizy, gdy większość danych dla tego wiersza/kolumny jest brakująca.\n",
|
|
"\n",
|
|
"Oprócz identyfikowania brakujących wartości, pandas oferuje wygodny sposób na usuwanie 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": [
|
|
"Zauważ, że powinno to wyglądać jak wynik z `example3[example3.notnull()]`. Różnica polega na tym, że zamiast indeksować tylko na podstawie zamaskowanych wartości, `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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>0</th>\n",
|
|
" <th>1</th>\n",
|
|
" <th>2</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>1.0</td>\n",
|
|
" <td>NaN</td>\n",
|
|
" <td>7</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>2.0</td>\n",
|
|
" <td>5.0</td>\n",
|
|
" <td>8</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>NaN</td>\n",
|
|
" <td>6.0</td>\n",
|
|
" <td>9</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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 zmienił typ dwóch kolumn na float, aby uwzględnić `NaN`?)\n",
|
|
"\n",
|
|
"Nie można usunąć pojedynczej wartości z `DataFrame`, więc trzeba usunąć całe wiersze lub kolumny. W zależności od tego, co robisz, możesz chcieć wybrać jedną z tych opcji, dlatego pandas daje możliwość obu. Ponieważ w nauce o danych kolumny zazwyczaj reprezentują zmienne, a wiersze obserwacje, częściej usuwa się wiersze danych; domyślne ustawienie dla `dropna()` polega na usunięciu 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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>0</th>\n",
|
|
" <th>1</th>\n",
|
|
" <th>2</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>2.0</td>\n",
|
|
" <td>5.0</td>\n",
|
|
" <td>8</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>2</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>7</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>8</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>9</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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ć usunięcie dużej ilości danych, które być może chciałbyś zachować, szczególnie w przypadku mniejszych zbiorów danych. Co jeśli chcesz usunąć tylko 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 sprawdzić samodzielnie lub zobaczyć, jakie inne parametry ma ta metoda, uruchom `example4.dropna?` w komórce kodu). Możesz alternatywnie określić `how='all'`, aby usunąć tylko wiersze lub kolumny, które zawierają wszystkie wartości null. Rozszerzmy nasz przykład `DataFrame`, aby zobaczyć to w działaniu 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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>0</th>\n",
|
|
" <th>1</th>\n",
|
|
" <th>2</th>\n",
|
|
" <th>3</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>1.0</td>\n",
|
|
" <td>NaN</td>\n",
|
|
" <td>7</td>\n",
|
|
" <td>NaN</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>2.0</td>\n",
|
|
" <td>5.0</td>\n",
|
|
" <td>8</td>\n",
|
|
" <td>NaN</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>NaN</td>\n",
|
|
" <td>6.0</td>\n",
|
|
" <td>9</td>\n",
|
|
" <td>NaN</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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ę *niepustych* wartości, które wiersz lub kolumna musi mieć, aby zostać zachowanym:\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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>0</th>\n",
|
|
" <th>1</th>\n",
|
|
" <th>2</th>\n",
|
|
" <th>3</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>2.0</td>\n",
|
|
" <td>5.0</td>\n",
|
|
" <td>8</td>\n",
|
|
" <td>NaN</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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 pierwsza i ostatnia wiersz zostały usunięte, ponieważ zawierają tylko dwie niepuste wartości.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "mCcxLGyUgRsG"
|
|
},
|
|
"source": [
|
|
"### Wypełnianie wartości null\n",
|
|
"\n",
|
|
"Czasami warto wypełnić brakujące wartości takimi, które mogą być uznane za prawidłowe. Istnieje kilka technik wypełniania wartości null. Pierwszą z nich jest wykorzystanie wiedzy dziedzinowej (wiedzy na temat tematu, na którym opiera się zestaw danych), aby w pewien sposób oszacować 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 wypełnienia. Ponieważ jest to tak powszechne 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 zestawach 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. Na przykład, mamy 100 punktów danych, z czego 90 wskazało Prawda, 8 wskazało Fałsz, a 2 nie wypełniły. Wówczas 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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>0</th>\n",
|
|
" <th>1</th>\n",
|
|
" <th>2</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>1</td>\n",
|
|
" <td>2</td>\n",
|
|
" <td>True</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>3</td>\n",
|
|
" <td>4</td>\n",
|
|
" <td>None</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>5</td>\n",
|
|
" <td>6</td>\n",
|
|
" <td>False</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>7</td>\n",
|
|
" <td>8</td>\n",
|
|
" <td>True</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>4</th>\n",
|
|
" <td>9</td>\n",
|
|
" <td>10</td>\n",
|
|
" <td>True</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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": [
|
|
"Teraz najpierw znajdźmy modę, zanim wypełnimy wartość `None` modą.\n"
|
|
]
|
|
},
|
|
{
|
|
"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": [
|
|
"Więc zastąpimy None wartością True\n"
|
|
]
|
|
},
|
|
{
|
|
"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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>0</th>\n",
|
|
" <th>1</th>\n",
|
|
" <th>2</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>1</td>\n",
|
|
" <td>2</td>\n",
|
|
" <td>True</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>3</td>\n",
|
|
" <td>4</td>\n",
|
|
" <td>True</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>5</td>\n",
|
|
" <td>6</td>\n",
|
|
" <td>False</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>7</td>\n",
|
|
" <td>8</td>\n",
|
|
" <td>True</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>4</th>\n",
|
|
" <td>9</td>\n",
|
|
" <td>10</td>\n",
|
|
" <td>True</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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 mogliśmy wpisać cokolwiek zamiast `'True'` i zostałoby to podstawione.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "heYe1I0dOmQ_"
|
|
},
|
|
"source": [
|
|
"### Dane numeryczne\n",
|
|
"Przejdźmy teraz do danych numerycznych. W tym przypadku mamy dwa popularne 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 jest rozkładem normalnym, i uzupełnijmy brakujące wartości średnią z 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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>0</th>\n",
|
|
" <th>1</th>\n",
|
|
" <th>2</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>-2.0</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>1</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>-1.0</td>\n",
|
|
" <td>2</td>\n",
|
|
" <td>3</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>NaN</td>\n",
|
|
" <td>4</td>\n",
|
|
" <td>5</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>1.0</td>\n",
|
|
" <td>6</td>\n",
|
|
" <td>7</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>4</th>\n",
|
|
" <td>2.0</td>\n",
|
|
" <td>8</td>\n",
|
|
" <td>9</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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": [
|
|
"Wypełnianie średnią\n"
|
|
]
|
|
},
|
|
{
|
|
"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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>0</th>\n",
|
|
" <th>1</th>\n",
|
|
" <th>2</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>-2.0</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>1</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>-1.0</td>\n",
|
|
" <td>2</td>\n",
|
|
" <td>3</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>4</td>\n",
|
|
" <td>5</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>1.0</td>\n",
|
|
" <td>6</td>\n",
|
|
" <td>7</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>4</th>\n",
|
|
" <td>2.0</td>\n",
|
|
" <td>8</td>\n",
|
|
" <td>9</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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 innego dataframe, 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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>0</th>\n",
|
|
" <th>1</th>\n",
|
|
" <th>2</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>-2</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>1</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>-1</td>\n",
|
|
" <td>2.0</td>\n",
|
|
" <td>3</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>0</td>\n",
|
|
" <td>NaN</td>\n",
|
|
" <td>5</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>1</td>\n",
|
|
" <td>6.0</td>\n",
|
|
" <td>7</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>4</th>\n",
|
|
" <td>2</td>\n",
|
|
" <td>8.0</td>\n",
|
|
" <td>9</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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": [
|
|
"Wypełnianie medianą\n"
|
|
]
|
|
},
|
|
{
|
|
"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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>0</th>\n",
|
|
" <th>1</th>\n",
|
|
" <th>2</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>-2</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>1</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>-1</td>\n",
|
|
" <td>2.0</td>\n",
|
|
" <td>3</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>0</td>\n",
|
|
" <td>4.0</td>\n",
|
|
" <td>5</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>1</td>\n",
|
|
" <td>6.0</td>\n",
|
|
" <td>7</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>4</th>\n",
|
|
" <td>2</td>\n",
|
|
" <td>8.0</td>\n",
|
|
" <td>9</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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ć wykonywane, gdy danych jest niewiele lub istnieje strategia ich uzupełnienia.\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ępne prawidłowe wartości wstecz w celu wypełnienia 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 są 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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>0</th>\n",
|
|
" <th>1</th>\n",
|
|
" <th>2</th>\n",
|
|
" <th>3</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>1.0</td>\n",
|
|
" <td>NaN</td>\n",
|
|
" <td>7</td>\n",
|
|
" <td>NaN</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>2.0</td>\n",
|
|
" <td>5.0</td>\n",
|
|
" <td>8</td>\n",
|
|
" <td>NaN</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>NaN</td>\n",
|
|
" <td>6.0</td>\n",
|
|
" <td>9</td>\n",
|
|
" <td>NaN</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>0</th>\n",
|
|
" <th>1</th>\n",
|
|
" <th>2</th>\n",
|
|
" <th>3</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>1.0</td>\n",
|
|
" <td>1.0</td>\n",
|
|
" <td>7.0</td>\n",
|
|
" <td>7.0</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>2.0</td>\n",
|
|
" <td>5.0</td>\n",
|
|
" <td>8.0</td>\n",
|
|
" <td>8.0</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>NaN</td>\n",
|
|
" <td>6.0</td>\n",
|
|
" <td>9.0</td>\n",
|
|
" <td>9.0</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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życiu `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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>0</th>\n",
|
|
" <th>1</th>\n",
|
|
" <th>2</th>\n",
|
|
" <th>3</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>1.0</td>\n",
|
|
" <td>5.5</td>\n",
|
|
" <td>7</td>\n",
|
|
" <td>NaN</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>2.0</td>\n",
|
|
" <td>5.0</td>\n",
|
|
" <td>8</td>\n",
|
|
" <td>NaN</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>1.5</td>\n",
|
|
" <td>6.0</td>\n",
|
|
" <td>9</td>\n",
|
|
" <td>NaN</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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ślnym kierunkiem jest 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 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, a jedna z kolumn zawiera ich klasę spośród następujących ['klasa biznesowa', 'klasa ekonomiczna', 'pierwsza klasa']. 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 nadchodzących 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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>ID</th>\n",
|
|
" <th>class</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>10</td>\n",
|
|
" <td>business class</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>20</td>\n",
|
|
" <td>first class</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>30</td>\n",
|
|
" <td>economy class</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>40</td>\n",
|
|
" <td>economy class</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>4</th>\n",
|
|
" <td>50</td>\n",
|
|
" <td>economy class</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>5</th>\n",
|
|
" <td>60</td>\n",
|
|
" <td>business class</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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 w pierwszej kolumnie, musimy najpierw opisać mapowanie każdej klasy na liczbę, zanim dokonamy zamiany\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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>ID</th>\n",
|
|
" <th>class</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>10</td>\n",
|
|
" <td>0</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>20</td>\n",
|
|
" <td>2</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>30</td>\n",
|
|
" <td>1</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>40</td>\n",
|
|
" <td>1</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>4</th>\n",
|
|
" <td>50</td>\n",
|
|
" <td>1</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>5</th>\n",
|
|
" <td>60</td>\n",
|
|
" <td>0</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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 odpowiada temu, czego się spodziewaliśmy. 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**\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żdy punkt danych otrzymuje 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 zestawu 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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>ID</th>\n",
|
|
" <th>class</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>10</td>\n",
|
|
" <td>business class</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>20</td>\n",
|
|
" <td>first class</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>30</td>\n",
|
|
" <td>economy class</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>40</td>\n",
|
|
" <td>economy class</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>4</th>\n",
|
|
" <td>50</td>\n",
|
|
" <td>economy class</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>5</th>\n",
|
|
" <td>60</td>\n",
|
|
" <td>business class</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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 kodowanie one hot 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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>ID</th>\n",
|
|
" <th>class_business class</th>\n",
|
|
" <th>class_economy class</th>\n",
|
|
" <th>class_first class</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>10</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>0</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>20</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>1</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>30</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>40</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>4</th>\n",
|
|
" <td>50</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>5</th>\n",
|
|
" <td>60</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>0</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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 zawiera 0 lub 1, co określa, czy dana kategoria istnieje dla danego 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": [
|
|
"> Najważniejsze informacje:\n",
|
|
"1. Kodowanie służy do przekształcania danych nienumerycznych na dane numeryczne.\n",
|
|
"2. Istnieją dwa rodzaje kodowania: kodowanie etykiet oraz kodowanie One Hot, które można zastosować w zależności od wymagań zestawu danych.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "K8UXOJYRgRsJ"
|
|
},
|
|
"source": [
|
|
"## Usuwanie zduplikowanych danych\n",
|
|
"\n",
|
|
"> **Cel nauki:** Po zakończeniu tej części powinieneś swobodnie identyfikować i usuwać zduplikowane wartości z DataFrames.\n",
|
|
"\n",
|
|
"Oprócz brakujących danych, w rzeczywistych zestawach danych często napotkasz zduplikowane dane. Na szczęście pandas oferuje łatwy sposób wykrywania i usuwania zduplikowanych wpisów.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "qrEG-Wa0gRsJ"
|
|
},
|
|
"source": [
|
|
"### Identyfikacja duplikatów: `duplicated`\n",
|
|
"\n",
|
|
"Możesz łatwo wykryć zduplikowane wartości za pomocą metody `duplicated` w pandas, która zwraca maskę logiczną wskazującą, czy wpis w `DataFrame` jest duplikatem wcześniejszego. Stwórzmy kolejny przykład `DataFrame`, aby zobaczyć to 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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>letters</th>\n",
|
|
" <th>numbers</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>A</td>\n",
|
|
" <td>1</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>B</td>\n",
|
|
" <td>2</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>A</td>\n",
|
|
" <td>1</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>B</td>\n",
|
|
" <td>3</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>4</th>\n",
|
|
" <td>B</td>\n",
|
|
" <td>3</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>letters</th>\n",
|
|
" <th>numbers</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>A</td>\n",
|
|
" <td>1</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>B</td>\n",
|
|
" <td>2</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>B</td>\n",
|
|
" <td>3</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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ą analizować 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": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>letters</th>\n",
|
|
" <th>numbers</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>A</td>\n",
|
|
" <td>1</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>B</td>\n",
|
|
" <td>2</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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": [
|
|
"> **Wniosek:** Usuwanie zduplikowanych danych jest kluczowym elementem niemal każdego projektu z zakresu nauki o danych. Zduplikowane dane mogą zmienić wyniki analiz i prowadzić do nieprawidłowych rezultatów!\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Kontrole jakości danych w rzeczywistych zastosowaniach\n",
|
|
"\n",
|
|
"> **Cel nauki:** Po zakończeniu tej sekcji powinieneś swobodnie wykrywać i poprawiać typowe problemy z jakością danych w rzeczywistych zastosowaniach, takie jak niespójne wartości kategorii, nietypowe wartości numeryczne (wartości odstające) oraz duplikaty encji z wariacjami.\n",
|
|
"\n",
|
|
"Chociaż brakujące wartości i dokładne duplikaty są częstymi problemami, rzeczywiste zestawy danych często zawierają bardziej subtelne trudności:\n",
|
|
"\n",
|
|
"1. **Niespójne wartości kategorii**: Ta sama kategoria zapisana w różny sposób (np. \"USA\", \"U.S.A\", \"United States\")\n",
|
|
"2. **Nietypowe wartości numeryczne**: Ekstremalne wartości odstające wskazujące na błędy wprowadzania danych (np. wiek = 999)\n",
|
|
"3. **Prawie identyczne wiersze**: Rekordy reprezentujące tę samą encję z drobnymi różnicami\n",
|
|
"\n",
|
|
"Przyjrzyjmy się technikom wykrywania i radzenia sobie z tymi problemami.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Tworzenie przykładowego \"zanieczyszczonego\" zestawu danych\n",
|
|
"\n",
|
|
"Najpierw stwórzmy przykładowy zestaw danych, który zawiera typowe problemy, z jakimi często spotykamy się w danych rzeczywistych:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import pandas as pd\n",
|
|
"import numpy as np\n",
|
|
"\n",
|
|
"# Create a sample dataset with quality issues\n",
|
|
"dirty_data = pd.DataFrame({\n",
|
|
" 'customer_id': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],\n",
|
|
" 'name': ['John Smith', 'Jane Doe', 'John Smith', 'Bob Johnson', \n",
|
|
" 'Alice Williams', 'Charlie Brown', 'John Smith', 'Eva Martinez',\n",
|
|
" 'Bob Johnson', 'Diana Prince', 'Frank Castle', 'Alice Williams'],\n",
|
|
" 'age': [25, 32, 25, 45, 28, 199, 25, 31, 45, 27, -5, 28],\n",
|
|
" 'country': ['USA', 'UK', 'U.S.A', 'Canada', 'USA', 'United Kingdom',\n",
|
|
" 'United States', 'Mexico', 'canada', 'USA', 'UK', 'usa'],\n",
|
|
" 'purchase_amount': [100.50, 250.00, 105.00, 320.00, 180.00, 90.00,\n",
|
|
" 102.00, 275.00, 325.00, 195.00, 410.00, 185.00]\n",
|
|
"})\n",
|
|
"\n",
|
|
"print(\"Sample 'Dirty' Dataset:\")\n",
|
|
"print(dirty_data)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 1. Wykrywanie niespójnych wartości kategorii\n",
|
|
"\n",
|
|
"Zauważ, że kolumna `country` zawiera różne reprezentacje tych samych krajów. Zidentyfikujmy te niespójności:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Check unique values in the country column\n",
|
|
"print(\"Unique country values:\")\n",
|
|
"print(dirty_data['country'].unique())\n",
|
|
"print(f\"\\nTotal unique values: {dirty_data['country'].nunique()}\")\n",
|
|
"\n",
|
|
"# Count occurrences of each variation\n",
|
|
"print(\"\\nValue counts:\")\n",
|
|
"print(dirty_data['country'].value_counts())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Standaryzacja wartości kategorycznych\n",
|
|
"\n",
|
|
"Możemy stworzyć mapowanie, aby ujednolicić te wartości. Prostym podejściem jest konwersja na małe litery i utworzenie słownika mapowania:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Create a standardization mapping\n",
|
|
"country_mapping = {\n",
|
|
" 'usa': 'USA',\n",
|
|
" 'u.s.a': 'USA',\n",
|
|
" 'united states': 'USA',\n",
|
|
" 'uk': 'UK',\n",
|
|
" 'united kingdom': 'UK',\n",
|
|
" 'canada': 'Canada',\n",
|
|
" 'mexico': 'Mexico'\n",
|
|
"}\n",
|
|
"\n",
|
|
"# Standardize the country column\n",
|
|
"dirty_data['country_clean'] = dirty_data['country'].str.lower().map(country_mapping)\n",
|
|
"\n",
|
|
"print(\"Before standardization:\")\n",
|
|
"print(dirty_data['country'].value_counts())\n",
|
|
"print(\"\\nAfter standardization:\")\n",
|
|
"print(dirty_data[['country_clean']].value_counts())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"**Alternatywa: Użycie dopasowania przybliżonego**\n",
|
|
"\n",
|
|
"W bardziej złożonych przypadkach możemy użyć dopasowania przybliżonego ciągów znaków za pomocą biblioteki `rapidfuzz`, aby automatycznie wykrywać podobne ciągi:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"try:\n",
|
|
" from rapidfuzz import process, fuzz\n",
|
|
"except ImportError:\n",
|
|
" print(\"rapidfuzz is not installed. Please install it with 'pip install rapidfuzz' to use fuzzy matching.\")\n",
|
|
" process = None\n",
|
|
" fuzz = None\n",
|
|
"\n",
|
|
"# Get unique countries\n",
|
|
"unique_countries = dirty_data['country'].unique()\n",
|
|
"\n",
|
|
"# For each country, find similar matches\n",
|
|
"if process is not None and fuzz is not None:\n",
|
|
" print(\"Finding similar country names (similarity > 70%):\")\n",
|
|
" for country in unique_countries:\n",
|
|
" matches = process.extract(country, unique_countries, scorer=fuzz.ratio, limit=3)\n",
|
|
" # Filter matches with similarity > 70 and not identical\n",
|
|
" similar = [m for m in matches if m[1] > 70 and m[0] != country]\n",
|
|
" if similar:\n",
|
|
" print(f\"\\n'{country}' is similar to:\")\n",
|
|
" for match, score, _ in similar:\n",
|
|
" print(f\" - '{match}' (similarity: {score}%)\")\n",
|
|
"else:\n",
|
|
" print(\"Skipping fuzzy matching because rapidfuzz is not available.\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 2. Wykrywanie nietypowych wartości liczbowych (odchylenia)\n",
|
|
"\n",
|
|
"Przyglądając się kolumnie `age`, zauważamy podejrzane wartości, takie jak 199 i -5. Skorzystajmy z metod statystycznych, aby wykryć te odchylenia.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Display basic statistics\n",
|
|
"print(\"Age column statistics:\")\n",
|
|
"print(dirty_data['age'].describe())\n",
|
|
"\n",
|
|
"# Identify impossible values using domain knowledge\n",
|
|
"print(\"\\nRows with impossible age values (< 0 or > 120):\")\n",
|
|
"impossible_ages = dirty_data[(dirty_data['age'] < 0) | (dirty_data['age'] > 120)]\n",
|
|
"print(impossible_ages[['customer_id', 'name', 'age']])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Korzystanie z metody IQR (Interquartile Range)\n",
|
|
"\n",
|
|
"Metoda IQR to solidna technika statystyczna do wykrywania wartości odstających, która jest mniej wrażliwa na wartości skrajne:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Calculate IQR for age (excluding impossible values)\n",
|
|
"valid_ages = dirty_data[(dirty_data['age'] >= 0) & (dirty_data['age'] <= 120)]['age']\n",
|
|
"\n",
|
|
"Q1 = valid_ages.quantile(0.25)\n",
|
|
"Q3 = valid_ages.quantile(0.75)\n",
|
|
"IQR = Q3 - Q1\n",
|
|
"\n",
|
|
"# Define outlier bounds\n",
|
|
"lower_bound = Q1 - 1.5 * IQR\n",
|
|
"upper_bound = Q3 + 1.5 * IQR\n",
|
|
"\n",
|
|
"print(f\"IQR-based outlier bounds for age: [{lower_bound:.2f}, {upper_bound:.2f}]\")\n",
|
|
"\n",
|
|
"# Identify outliers\n",
|
|
"age_outliers = dirty_data[(dirty_data['age'] < lower_bound) | (dirty_data['age'] > upper_bound)]\n",
|
|
"print(f\"\\nRows with age outliers:\")\n",
|
|
"print(age_outliers[['customer_id', 'name', 'age']])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Korzystanie z metody Z-score\n",
|
|
"\n",
|
|
"Metoda Z-score identyfikuje wartości odstające na podstawie odchyleń standardowych od średniej:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"try:\n",
|
|
" from scipy import stats\n",
|
|
"except ImportError:\n",
|
|
" print(\"scipy is required for Z-score calculation. Please install it with 'pip install scipy' and rerun this cell.\")\n",
|
|
"else:\n",
|
|
" # Calculate Z-scores for age, handling NaN values\n",
|
|
" age_nonan = dirty_data['age'].dropna()\n",
|
|
" zscores = np.abs(stats.zscore(age_nonan))\n",
|
|
" dirty_data['age_zscore'] = np.nan\n",
|
|
" dirty_data.loc[age_nonan.index, 'age_zscore'] = zscores\n",
|
|
"\n",
|
|
" # Typically, Z-score > 3 indicates an outlier\n",
|
|
" print(\"Rows with age Z-score > 3:\")\n",
|
|
" zscore_outliers = dirty_data[dirty_data['age_zscore'] > 3]\n",
|
|
" print(zscore_outliers[['customer_id', 'name', 'age', 'age_zscore']])\n",
|
|
"\n",
|
|
" # Clean up the temporary column\n",
|
|
" dirty_data = dirty_data.drop('age_zscore', axis=1)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Obsługa wartości odstających\n",
|
|
"\n",
|
|
"Po ich wykryciu, wartości odstające można obsłużyć na kilka sposobów:\n",
|
|
"1. **Usuń**: Usuń wiersze zawierające wartości odstające (jeśli są błędami)\n",
|
|
"2. **Ogranicz**: Zastąp wartościami granicznymi\n",
|
|
"3. **Zastąp NaN**: Potraktuj jako brakujące dane i zastosuj techniki imputacji\n",
|
|
"4. **Zachowaj**: Jeśli są to uzasadnione wartości ekstremalne\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Create a cleaned version by replacing impossible ages with NaN\n",
|
|
"dirty_data['age_clean'] = dirty_data['age'].apply(\n",
|
|
" lambda x: np.nan if (x < 0 or x > 120) else x\n",
|
|
")\n",
|
|
"\n",
|
|
"print(\"Age column before and after cleaning:\")\n",
|
|
"print(dirty_data[['customer_id', 'name', 'age', 'age_clean']])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 3. Wykrywanie prawie identycznych wierszy\n",
|
|
"\n",
|
|
"Zauważ, że nasz zestaw danych zawiera wiele wpisów dla \"John Smith\" z nieco różniącymi się wartościami. Zidentyfikujmy potencjalne duplikaty na podstawie podobieństwa nazw.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# First, let's look at exact name matches (ignoring extra whitespace)\n",
|
|
"dirty_data['name_normalized'] = dirty_data['name'].str.strip().str.lower()\n",
|
|
"\n",
|
|
"print(\"Checking for duplicate names:\")\n",
|
|
"duplicate_names = dirty_data[dirty_data.duplicated(['name_normalized'], keep=False)]\n",
|
|
"print(duplicate_names.sort_values('name_normalized')[['customer_id', 'name', 'age', 'country']])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Znajdowanie prawie identycznych elementów za pomocą dopasowania rozmytego\n",
|
|
"\n",
|
|
"Do bardziej zaawansowanego wykrywania duplikatów możemy użyć dopasowania rozmytego, aby znaleźć podobne nazwy:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"try:\n",
|
|
" from rapidfuzz import process, fuzz\n",
|
|
"\n",
|
|
" # Function to find potential duplicates\n",
|
|
" def find_near_duplicates(df, column, threshold=90):\n",
|
|
" \"\"\"\n",
|
|
" Find near-duplicate entries in a column using fuzzy matching.\n",
|
|
" \n",
|
|
" Parameters:\n",
|
|
" - df: DataFrame\n",
|
|
" - column: Column name to check for duplicates\n",
|
|
" - threshold: Similarity threshold (0-100)\n",
|
|
" \n",
|
|
" Returns: List of potential duplicate groups\n",
|
|
" \"\"\"\n",
|
|
" values = df[column].unique()\n",
|
|
" duplicate_groups = []\n",
|
|
" checked = set()\n",
|
|
" \n",
|
|
" for value in values:\n",
|
|
" if value in checked:\n",
|
|
" continue\n",
|
|
" \n",
|
|
" # Find similar values\n",
|
|
" matches = process.extract(value, values, scorer=fuzz.ratio, limit=len(values))\n",
|
|
" similar = [m[0] for m in matches if m[1] >= threshold]\n",
|
|
" \n",
|
|
" if len(similar) > 1:\n",
|
|
" duplicate_groups.append(similar)\n",
|
|
" checked.update(similar)\n",
|
|
" \n",
|
|
" return duplicate_groups\n",
|
|
"\n",
|
|
" # Find near-duplicate names\n",
|
|
" duplicate_groups = find_near_duplicates(dirty_data, 'name', threshold=90)\n",
|
|
"\n",
|
|
" print(\"Potential duplicate groups:\")\n",
|
|
" for i, group in enumerate(duplicate_groups, 1):\n",
|
|
" print(f\"\\nGroup {i}:\")\n",
|
|
" for name in group:\n",
|
|
" matching_rows = dirty_data[dirty_data['name'] == name]\n",
|
|
" print(f\" '{name}': {len(matching_rows)} occurrence(s)\")\n",
|
|
" for _, row in matching_rows.iterrows():\n",
|
|
" print(f\" - Customer {row['customer_id']}: age={row['age']}, country={row['country']}\")\n",
|
|
"except ImportError:\n",
|
|
" print(\"rapidfuzz is not installed. Skipping fuzzy matching for near-duplicates.\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Obsługa duplikatów\n",
|
|
"\n",
|
|
"Po zidentyfikowaniu, musisz zdecydować, jak obsłużyć duplikaty:\n",
|
|
"1. **Zachowaj pierwsze wystąpienie**: Użyj `drop_duplicates(keep='first')`\n",
|
|
"2. **Zachowaj ostatnie wystąpienie**: Użyj `drop_duplicates(keep='last')`\n",
|
|
"3. **Agreguj informacje**: Połącz informacje z duplikowanych wierszy\n",
|
|
"4. **Ręczna weryfikacja**: Oznacz do przeglądu przez człowieka\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Example: Remove duplicates based on normalized name, keeping first occurrence\n",
|
|
"cleaned_data = dirty_data.drop_duplicates(subset=['name_normalized'], keep='first')\n",
|
|
"\n",
|
|
"print(f\"Original dataset: {len(dirty_data)} rows\")\n",
|
|
"print(f\"After removing name duplicates: {len(cleaned_data)} rows\")\n",
|
|
"print(f\"Removed: {len(dirty_data) - len(cleaned_data)} duplicate rows\")\n",
|
|
"\n",
|
|
"print(\"\\nCleaned dataset:\")\n",
|
|
"print(cleaned_data[['customer_id', 'name', 'age', 'country_clean']])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Podsumowanie: Kompletny Proces Czyszczenia Danych\n",
|
|
"\n",
|
|
"Połączmy wszystko w jeden kompleksowy proces czyszczenia danych:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def clean_dataset(df):\n",
|
|
" \"\"\"\n",
|
|
" Comprehensive data cleaning function.\n",
|
|
" \"\"\"\n",
|
|
" # Create a copy to avoid modifying the original\n",
|
|
" cleaned = df.copy()\n",
|
|
" \n",
|
|
" # 1. Standardize categorical values (country)\n",
|
|
" country_mapping = {\n",
|
|
" 'usa': 'USA', 'u.s.a': 'USA', 'united states': 'USA',\n",
|
|
" 'uk': 'UK', 'united kingdom': 'UK',\n",
|
|
" 'canada': 'Canada', 'mexico': 'Mexico'\n",
|
|
" }\n",
|
|
" cleaned['country'] = cleaned['country'].str.lower().map(country_mapping)\n",
|
|
" \n",
|
|
" # 2. Clean abnormal age values\n",
|
|
" cleaned['age'] = cleaned['age'].apply(\n",
|
|
" lambda x: np.nan if (x < 0 or x > 120) else x\n",
|
|
" )\n",
|
|
" \n",
|
|
" # 3. Remove near-duplicate names (normalize whitespace)\n",
|
|
" cleaned['name'] = cleaned['name'].str.strip()\n",
|
|
" cleaned = cleaned.drop_duplicates(subset=['name'], keep='first')\n",
|
|
" \n",
|
|
" return cleaned\n",
|
|
"\n",
|
|
"# Apply the cleaning pipeline\n",
|
|
"final_cleaned_data = clean_dataset(dirty_data)\n",
|
|
"\n",
|
|
"print(\"Before cleaning:\")\n",
|
|
"print(f\" Rows: {len(dirty_data)}\")\n",
|
|
"print(f\" Unique countries: {dirty_data['country'].nunique()}\")\n",
|
|
"print(f\" Invalid ages: {((dirty_data['age'] < 0) | (dirty_data['age'] > 120)).sum()}\")\n",
|
|
"\n",
|
|
"print(\"\\nAfter cleaning:\")\n",
|
|
"print(f\" Rows: {len(final_cleaned_data)}\")\n",
|
|
"print(f\" Unique countries: {final_cleaned_data['country'].nunique()}\")\n",
|
|
"print(f\" Invalid ages: {((final_cleaned_data['age'] < 0) | (final_cleaned_data['age'] > 120)).sum()}\")\n",
|
|
"\n",
|
|
"print(\"\\nCleaned dataset:\")\n",
|
|
"print(final_cleaned_data[['customer_id', 'name', 'age', 'country', 'purchase_amount']])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 🎯 Ćwiczenie Wyzwanie\n",
|
|
"\n",
|
|
"Teraz Twoja kolej! Poniżej znajduje się nowy wiersz danych z wieloma problemami jakościowymi. Czy potrafisz:\n",
|
|
"\n",
|
|
"1. Zidentyfikować wszystkie problemy w tym wierszu\n",
|
|
"2. Napisać kod, aby naprawić każdy problem\n",
|
|
"3. Dodać oczyszczony wiersz do zestawu danych\n",
|
|
"\n",
|
|
"Oto problematyczne dane:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# New problematic row\n",
|
|
"new_row = pd.DataFrame({\n",
|
|
" 'customer_id': [13],\n",
|
|
" 'name': [' Diana Prince '], # Extra whitespace\n",
|
|
" 'age': [250], # Impossible age\n",
|
|
" 'country': ['U.S.A.'], # Inconsistent format\n",
|
|
" 'purchase_amount': [150.00]\n",
|
|
"})\n",
|
|
"\n",
|
|
"print(\"New row to clean:\")\n",
|
|
"print(new_row)\n",
|
|
"\n",
|
|
"# TODO: Your code here to clean this row\n",
|
|
"# Hints:\n",
|
|
"# 1. Strip whitespace from the name\n",
|
|
"# 2. Check if the name is a duplicate (Diana Prince already exists)\n",
|
|
"# 3. Handle the impossible age value\n",
|
|
"# 4. Standardize the country name\n",
|
|
"\n",
|
|
"# Example solution (uncomment and modify as needed):\n",
|
|
"# new_row_cleaned = new_row.copy()\n",
|
|
"# new_row_cleaned['name'] = new_row_cleaned['name'].str.strip()\n",
|
|
"# new_row_cleaned['age'] = np.nan # Invalid age\n",
|
|
"# new_row_cleaned['country'] = 'USA' # Standardized\n",
|
|
"# print(\"\\nCleaned row:\")\n",
|
|
"# print(new_row_cleaned)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Kluczowe Wnioski\n",
|
|
"\n",
|
|
"1. **Niespójne kategorie** są częstym problemem w danych rzeczywistych. Zawsze sprawdzaj unikalne wartości i standaryzuj je za pomocą mapowań lub dopasowania przybliżonego.\n",
|
|
"\n",
|
|
"2. **Wartości odstające** mogą znacząco wpłynąć na Twoją analizę. Wykorzystaj wiedzę domenową w połączeniu z metodami statystycznymi (IQR, Z-score), aby je wykryć.\n",
|
|
"\n",
|
|
"3. **Prawie duplikaty** są trudniejsze do wykrycia niż dokładne duplikaty. Rozważ użycie dopasowania przybliżonego oraz normalizację danych (zmiana na małe litery, usuwanie spacji), aby je zidentyfikować.\n",
|
|
"\n",
|
|
"4. **Czyszczenie danych jest procesem iteracyjnym**. Może być konieczne zastosowanie wielu technik i przegląd wyników przed ostatecznym zakończeniem procesu czyszczenia danych.\n",
|
|
"\n",
|
|
"5. **Dokumentuj swoje decyzje**. Zapisuj, jakie kroki czyszczenia danych zostały zastosowane i dlaczego, ponieważ jest to ważne dla odtwarzalności i przejrzystości.\n",
|
|
"\n",
|
|
"> **Najlepsza praktyka:** Zawsze zachowaj kopię swoich oryginalnych \"brudnych\" danych. Nigdy nie nadpisuj plików źródłowych - twórz oczyszczone wersje z jasnymi konwencjami nazewnictwa, np. `data_cleaned.csv`.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n---\n\n**Zastrzeżenie**: \nTen dokument został przetłumaczony za pomocą usługi tłumaczenia AI [Co-op Translator](https://github.com/Azure/co-op-translator). Chociaż staramy się zapewnić dokładność, prosimy pamiętać, że automatyczne tłumaczenia mogą zawierać błędy lub nieścisłości. Oryginalny dokument w jego języku źródłowym powinien być uznawany za autorytatywne źródło. W przypadku informacji krytycznych zaleca się skorzystanie z profesjonalnego tłumaczenia przez człowieka. Nie ponosimy odpowiedzialności za jakiekolwiek nieporozumienia lub błędne interpretacje wynikające z użycia 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": "6301339d1c9a301b00639c635dc9b731",
|
|
"translation_date": "2025-10-03T20:02:55+00:00",
|
|
"source_file": "2-Working-With-Data/08-data-preparation/notebook.ipynb",
|
|
"language_code": "pl"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 0
|
|
} |