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": [
|
|
"# Gegevensvoorbereiding\n",
|
|
"\n",
|
|
"[Originele Notebook-bron van *Data Science: Introduction to Machine Learning for Data Science Python and Machine Learning Studio door Lee Stott*](https://github.com/leestott/intro-Datascience/blob/master/Course%20Materials/4-Cleaning_and_Manipulating-Reference.ipynb)\n",
|
|
"\n",
|
|
"## Verkennen van `DataFrame`-informatie\n",
|
|
"\n",
|
|
"> **Leerdoel:** Aan het einde van deze subsectie moet je in staat zijn om algemene informatie over de gegevens die zijn opgeslagen in pandas DataFrames te vinden.\n",
|
|
"\n",
|
|
"Zodra je je gegevens in pandas hebt geladen, zullen ze hoogstwaarschijnlijk in een `DataFrame` staan. Maar als de dataset in je `DataFrame` 60.000 rijen en 400 kolommen bevat, hoe begin je dan überhaupt een idee te krijgen van waar je mee werkt? Gelukkig biedt pandas enkele handige tools om snel algemene informatie over een `DataFrame` te bekijken, naast de eerste paar en laatste paar rijen.\n",
|
|
"\n",
|
|
"Om deze functionaliteit te verkennen, importeren we de Python scikit-learn bibliotheek en gebruiken we een iconische dataset die elke datawetenschapper honderden keren heeft gezien: de *Iris*-dataset van de Britse bioloog Ronald Fisher, gebruikt in zijn paper uit 1936 \"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",
|
|
"We hebben de Iris Dataset geladen in de variabele `iris_df`. Voordat we de data gaan verkennen, is het handig om te weten hoeveel datapunten we hebben en wat de totale omvang van de dataset is. Het is nuttig om een idee te krijgen van de hoeveelheid data waarmee we werken.\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": [
|
|
"We hebben hier te maken met 150 rijen en 4 kolommen aan data. Elke rij vertegenwoordigt één datapunt en elke kolom staat voor een enkele eigenschap die bij het data frame hoort. Kortom, er zijn 150 datapunten met elk 4 eigenschappen.\n",
|
|
"\n",
|
|
"`shape` is hier een attribuut van het data frame en geen functie, daarom eindigt het niet met een paar haakjes.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "d3AZKs0PinGP"
|
|
},
|
|
"source": [
|
|
"### `DataFrame.columns`\n",
|
|
"Laten we nu de 4 kolommen van gegevens bekijken. Wat vertegenwoordigt elk van hen precies? De `columns`-eigenschap geeft ons de namen van de kolommen in de 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": [
|
|
"Zoals we kunnen zien, zijn er vier(4) kolommen. Het `columns`-attribuut vertelt ons de namen van de kolommen en verder eigenlijk niets. Dit attribuut wordt belangrijk wanneer we de kenmerken van een dataset willen identificeren.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "2UTlvkjmgRrs"
|
|
},
|
|
"source": [
|
|
"### `DataFrame.info`\n",
|
|
"De hoeveelheid data (gegeven door het attribuut `shape`) en de namen van de kenmerken of kolommen (gegeven door het attribuut `columns`) vertellen ons iets over de dataset. Nu willen we dieper in de dataset duiken. De functie `DataFrame.info()` is hier erg handig voor.\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": [
|
|
"Van hieruit kunnen we een paar observaties maken:\n",
|
|
"1. Het datatype van elke kolom: In deze dataset worden alle gegevens opgeslagen als 64-bit floating-point getallen.\n",
|
|
"2. Aantal niet-nulwaarden: Het omgaan met nullwaarden is een belangrijke stap in de voorbereiding van gegevens. Dit zal later in het notebook worden behandeld.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "IYlyxbpWFEF4"
|
|
},
|
|
"source": [
|
|
"### DataFrame.describe()\n",
|
|
"Stel dat we veel numerieke gegevens in onze dataset hebben. Univariate statistische berekeningen zoals het gemiddelde, de mediaan, kwartielen, enzovoort, kunnen afzonderlijk op elke kolom worden uitgevoerd. De functie `DataFrame.describe()` geeft ons een statistisch overzicht van de numerieke kolommen van een dataset.\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": [
|
|
"De bovenstaande output toont het totale aantal datapunten, gemiddelde, standaarddeviatie, minimum, onderste kwartiel (25%), mediaan (50%), bovenste kwartiel (75%) en de maximale waarde van elke kolom.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "-lviAu99gRrv"
|
|
},
|
|
"source": [
|
|
"### `DataFrame.head`\n",
|
|
"Met alle bovenstaande functies en attributen hebben we een overzicht op hoog niveau van de dataset gekregen. We weten hoeveel datapunten er zijn, hoeveel kenmerken er zijn, het datatype van elk kenmerk en het aantal niet-nulwaarden voor elk kenmerk.\n",
|
|
"\n",
|
|
"Nu is het tijd om naar de gegevens zelf te kijken. Laten we eens zien hoe de eerste paar rijen (de eerste paar datapunten) van onze `DataFrame` eruitzien:\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": [
|
|
"Zoals we hier zien, zijn er vijf(5) vermeldingen van de dataset. Als we naar de index aan de linkerkant kijken, ontdekken we dat dit de eerste vijf rijen zijn.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "oj7GkrTdgRry"
|
|
},
|
|
"source": [
|
|
"### Oefening:\n",
|
|
"\n",
|
|
"Uit het bovenstaande voorbeeld blijkt dat `DataFrame.head` standaard de eerste vijf rijen van een `DataFrame` retourneert. Kun je in de onderstaande codecel een manier vinden om meer dan vijf rijen weer te geven?\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",
|
|
"Een andere manier om naar de gegevens te kijken is vanaf het einde (in plaats van het begin). De tegenhanger van `DataFrame.head` is `DataFrame.tail`, die de laatste vijf rijen van een `DataFrame` retourneert:\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": [
|
|
"In de praktijk is het handig om eenvoudig de eerste paar rijen of de laatste paar rijen van een `DataFrame` te bekijken, vooral wanneer je op zoek bent naar uitschieters in geordende datasets.\n",
|
|
"\n",
|
|
"Alle functies en attributen die hierboven zijn getoond met behulp van codevoorbeelden, helpen ons om een indruk te krijgen van de data.\n",
|
|
"\n",
|
|
"> **Belangrijk punt:** Alleen al door te kijken naar de metadata over de informatie in een DataFrame of naar de eerste en laatste paar waarden ervan, kun je direct een idee krijgen van de grootte, vorm en inhoud van de data waarmee je werkt.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "TvurZyLSDxq_"
|
|
},
|
|
"source": [
|
|
"### Ontbrekende Gegevens\n",
|
|
"Laten we ons verdiepen in ontbrekende gegevens. Ontbrekende gegevens ontstaan wanneer er geen waarde is opgeslagen in sommige kolommen.\n",
|
|
"\n",
|
|
"Laten we een voorbeeld nemen: stel dat iemand bewust is over zijn/haar gewicht en het veld voor gewicht niet invult in een enquête. Dan zal de waarde voor gewicht van die persoon ontbreken.\n",
|
|
"\n",
|
|
"In de meeste gevallen komen ontbrekende waarden voor in datasets uit de echte wereld.\n",
|
|
"\n",
|
|
"**Hoe Pandas omgaat met ontbrekende gegevens**\n",
|
|
"\n",
|
|
"Pandas gaat op twee manieren om met ontbrekende waarden. De eerste manier heb je al eerder gezien in vorige secties: `NaN`, of Not a Number. Dit is eigenlijk een speciale waarde die deel uitmaakt van de IEEE floating-point specificatie en wordt alleen gebruikt om ontbrekende waarden van het type float aan te geven.\n",
|
|
"\n",
|
|
"Voor ontbrekende waarden die geen floats zijn, gebruikt pandas het Python-object `None`. Hoewel het misschien verwarrend lijkt dat je twee verschillende soorten waarden tegenkomt die in essentie hetzelfde aangeven, zijn er goede programmatische redenen voor deze ontwerpkeuze. In de praktijk stelt deze aanpak pandas in staat om een goed compromis te bieden voor de overgrote meerderheid van de gevallen. Desondanks hebben zowel `None` als `NaN` beperkingen waar je rekening mee moet houden met betrekking tot hoe ze kunnen worden gebruikt.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "lOHqUlZFgRr5"
|
|
},
|
|
"source": [
|
|
"### `None`: niet-vloeiende ontbrekende gegevens\n",
|
|
"Omdat `None` afkomstig is uit Python, kan het niet worden gebruikt in NumPy- en pandas-arrays die geen datatype `'object'` hebben. Onthoud dat NumPy-arrays (en de datastructuren in pandas) slechts één type gegevens kunnen bevatten. Dit is wat hen hun enorme kracht geeft voor grootschalige data- en rekentaken, maar het beperkt ook hun flexibiliteit. Dergelijke arrays moeten worden opgewaardeerd naar de \"laagste gemene deler,\" het datatype dat alles in de array kan omvatten. Wanneer `None` in de array voorkomt, betekent dit dat je werkt met Python-objecten.\n",
|
|
"\n",
|
|
"Om dit in de praktijk te zien, bekijk het volgende voorbeeld van een array (let op de `dtype` ervan):\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": [
|
|
"De realiteit van opgehoogde datatypes brengt twee bijwerkingen met zich mee. Ten eerste worden bewerkingen uitgevoerd op het niveau van geïnterpreteerde Python-code in plaats van gecompileerde NumPy-code. In essentie betekent dit dat alle bewerkingen met `Series` of `DataFrames` waarin `None` voorkomt, langzamer zullen zijn. Hoewel je deze prestatievermindering waarschijnlijk niet zult opmerken, kan het bij grote datasets een probleem worden.\n",
|
|
"\n",
|
|
"De tweede bijwerking vloeit voort uit de eerste. Omdat `None` `Series` of `DataFrames` feitelijk terugbrengt naar de wereld van standaard Python, zal het gebruik van NumPy/pandas-aggregaties zoals `sum()` of `min()` op arrays die een ``None``-waarde bevatten, doorgaans een fout veroorzaken:\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": [
|
|
"**Belangrijkste punt**: Optelling (en andere bewerkingen) tussen gehele getallen en `None`-waarden is ongedefinieerd, wat kan beperken wat je kunt doen met datasets die deze bevatten.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "pWvVHvETgRr9"
|
|
},
|
|
"source": [
|
|
"### `NaN`: ontbrekende float-waarden\n",
|
|
"\n",
|
|
"In tegenstelling tot `None` ondersteunt NumPy (en dus ook pandas) `NaN` voor zijn snelle, gevectoriseerde bewerkingen en ufuncs. Het nadeel is dat elke rekenkundige bewerking met `NaN` altijd resulteert in `NaN`. Bijvoorbeeld:\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": [
|
|
"Het goede nieuws: aggregaties uitgevoerd op arrays met `NaN` erin veroorzaken geen fouten. Het slechte nieuws: de resultaten zijn niet uniform bruikbaar:\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": [
|
|
"### Oefening:\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": [
|
|
"Onthoud: `NaN` is alleen voor ontbrekende waarden met drijvende komma; er is geen `NaN`-equivalent voor gehele getallen, strings of Booleans.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "kj6EKdsAgRsA"
|
|
},
|
|
"source": [
|
|
"### `NaN` en `None`: nullwaarden in pandas\n",
|
|
"\n",
|
|
"Hoewel `NaN` en `None` zich enigszins anders kunnen gedragen, is pandas toch ontworpen om ze door elkaar te gebruiken. Om te begrijpen wat we bedoelen, bekijk een `Series` van gehele getallen:\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": [
|
|
"### Oefening:\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": [
|
|
"Bij het opwaarderen van gegevenstypen om gegevenshomogeniteit te bereiken in `Series` en `DataFrame`s, zal pandas zonder problemen ontbrekende waarden wisselen tussen `None` en `NaN`. Door deze ontwerpkeuze kan het nuttig zijn om `None` en `NaN` te beschouwen als twee verschillende varianten van \"null\" in pandas. Sterker nog, sommige van de kernmethoden die je zult gebruiken om met ontbrekende waarden in pandas om te gaan, weerspiegelen dit idee in hun namen:\n",
|
|
"\n",
|
|
"- `isnull()`: Genereert een Booleaanse maskering die ontbrekende waarden aangeeft\n",
|
|
"- `notnull()`: Tegenovergestelde van `isnull()`\n",
|
|
"- `dropna()`: Geeft een gefilterde versie van de gegevens terug\n",
|
|
"- `fillna()`: Geeft een kopie van de gegevens terug waarbij ontbrekende waarden zijn ingevuld of geïmputeerd\n",
|
|
"\n",
|
|
"Dit zijn belangrijke methoden om onder de knie te krijgen en vertrouwd mee te raken, dus laten we ze elk wat uitgebreider bespreken.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "Yh5ifd9FgRsB"
|
|
},
|
|
"source": [
|
|
"### Nullwaarden detecteren\n",
|
|
"\n",
|
|
"Nu we het belang van ontbrekende waarden hebben begrepen, moeten we ze in onze dataset opsporen voordat we ermee aan de slag gaan. Zowel `isnull()` als `notnull()` zijn je belangrijkste methoden om nullwaarden te detecteren. Beide geven Booleaanse maskers over je data terug.\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": [
|
|
"Kijk goed naar de output. Verrast iets je? Hoewel `0` een wiskundige nul is, is het toch een volwaardig geheel getal en pandas behandelt het ook zo. `''` is iets subtieler. Hoewel we het in Sectie 1 gebruikten om een lege tekenreekswaarde weer te geven, is het toch een tekenreeksobject en geen representatie van null volgens pandas.\n",
|
|
"\n",
|
|
"Laten we dit nu omdraaien en deze methoden gebruiken op een manier zoals je ze in de praktijk zult toepassen. Je kunt Booleaanse maskers direct gebruiken als een ``Series``- of ``DataFrame``-index, wat handig kan zijn wanneer je wilt werken met geïsoleerde ontbrekende (of aanwezige) waarden.\n",
|
|
"\n",
|
|
"Als we het totale aantal ontbrekende waarden willen weten, kunnen we gewoon een som nemen over het masker dat door de `isnull()`-methode wordt geproduceerd.\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": [
|
|
"### Oefening:\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": [
|
|
"**Belangrijkste inzicht**: Zowel de methoden `isnull()` als `notnull()` leveren vergelijkbare resultaten op wanneer je ze gebruikt in DataFrames: ze tonen de resultaten en de index van die resultaten, wat je enorm zal helpen bij het werken met je data.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "BvnoojWsgRr4"
|
|
},
|
|
"source": [
|
|
"### Omgaan met ontbrekende gegevens\n",
|
|
"\n",
|
|
"> **Leerdoel:** Aan het einde van deze subsectie weet je hoe en wanneer je null-waarden in DataFrames kunt vervangen of verwijderen.\n",
|
|
"\n",
|
|
"Machine Learning-modellen kunnen niet zelf omgaan met ontbrekende gegevens. Daarom moeten we, voordat we de gegevens aan het model doorgeven, deze ontbrekende waarden aanpakken.\n",
|
|
"\n",
|
|
"Hoe ontbrekende gegevens worden behandeld, brengt subtiele afwegingen met zich mee en kan invloed hebben op je uiteindelijke analyse en resultaten in de praktijk.\n",
|
|
"\n",
|
|
"Er zijn voornamelijk twee manieren om met ontbrekende gegevens om te gaan:\n",
|
|
"\n",
|
|
"1. De rij met de ontbrekende waarde verwijderen\n",
|
|
"2. De ontbrekende waarde vervangen door een andere waarde\n",
|
|
"\n",
|
|
"We zullen beide methoden en hun voor- en nadelen uitgebreid bespreken.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "3VaYC1TvgRsD"
|
|
},
|
|
"source": [
|
|
"### Nullwaarden verwijderen\n",
|
|
"\n",
|
|
"De hoeveelheid data die we aan ons model doorgeven, heeft een directe invloed op de prestaties ervan. Nullwaarden verwijderen betekent dat we het aantal datapunten verminderen en daarmee de grootte van de dataset verkleinen. Het is daarom aan te raden om rijen met nullwaarden te verwijderen wanneer de dataset behoorlijk groot is.\n",
|
|
"\n",
|
|
"Een andere situatie kan zijn dat een bepaalde rij of kolom veel ontbrekende waarden heeft. In dat geval kunnen ze worden verwijderd, omdat ze weinig waarde toevoegen aan onze analyse, aangezien de meeste gegevens voor die rij/kolom ontbreken.\n",
|
|
"\n",
|
|
"Naast het identificeren van ontbrekende waarden biedt pandas een handige manier om nullwaarden te verwijderen uit `Series` en `DataFrame`s. Om dit in de praktijk te zien, laten we teruggaan naar `example3`. De functie `DataFrame.dropna()` helpt bij het verwijderen van rijen met nullwaarden.\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": [
|
|
"Merk op dat dit eruit zou moeten zien als je uitvoer van `example3[example3.notnull()]`. Het verschil hier is dat, in plaats van alleen te indexeren op de gemaskeerde waarden, `dropna` die ontbrekende waarden uit de `Series` `example3` heeft verwijderd.\n",
|
|
"\n",
|
|
"Omdat DataFrames twee dimensies hebben, bieden ze meer opties om gegevens te verwijderen.\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": [
|
|
"(Heb je gemerkt dat pandas twee van de kolommen heeft omgezet naar floats om de `NaN`s te accommoderen?)\n",
|
|
"\n",
|
|
"Je kunt geen enkele waarde uit een `DataFrame` verwijderen, dus je moet volledige rijen of kolommen verwijderen. Afhankelijk van wat je aan het doen bent, wil je misschien het een of het ander doen, en daarom biedt pandas opties voor beide. Omdat in datawetenschap kolommen meestal variabelen vertegenwoordigen en rijen observaties, is de kans groter dat je rijen met gegevens verwijdert; de standaardinstelling voor `dropna()` is om alle rijen te verwijderen die null-waarden bevatten:\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": [
|
|
"Indien nodig kun je NA-waarden uit kolommen verwijderen. Gebruik `axis=1` om dit te doen:\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": [
|
|
"Merk op dat dit veel gegevens kan verwijderen die je misschien wilt behouden, vooral bij kleinere datasets. Wat als je alleen rijen of kolommen wilt verwijderen die meerdere of zelfs alle nullwaarden bevatten? Je kunt deze instellingen specificeren in `dropna` met de parameters `how` en `thresh`.\n",
|
|
"\n",
|
|
"Standaard is `how='any'` (als je dit zelf wilt controleren of wilt zien welke andere parameters de methode heeft, voer dan `example4.dropna?` uit in een codecel). Je kunt ook `how='all'` specificeren om alleen rijen of kolommen te verwijderen die volledig uit nullwaarden bestaan. Laten we ons voorbeeld `DataFrame` uitbreiden om dit in actie te zien in de volgende oefening.\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": [
|
|
"> Belangrijkste punten: \n",
|
|
"1. Het verwijderen van null-waarden is alleen een goed idee als de dataset groot genoeg is. \n",
|
|
"2. Volledige rijen of kolommen kunnen worden verwijderd als het merendeel van de gegevens ontbreekt. \n",
|
|
"3. De methode `DataFrame.dropna(axis=)` helpt bij het verwijderen van null-waarden. Het argument `axis` geeft aan of rijen of kolommen moeten worden verwijderd. \n",
|
|
"4. Het argument `how` kan ook worden gebruikt. Standaard is het ingesteld op `any`. Dit betekent dat alleen die rijen/kolommen worden verwijderd die een null-waarde bevatten. Het kan worden ingesteld op `all` om aan te geven dat we alleen die rijen/kolommen verwijderen waar alle waarden null zijn. \n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "oXXSfQFHgRsF"
|
|
},
|
|
"source": [
|
|
"### Oefening:\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": [
|
|
"De `thresh`-parameter geeft je meer gedetailleerde controle: je stelt het aantal *niet-nulle* waarden in dat een rij of kolom moet hebben om behouden te blijven:\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": [
|
|
"Hier zijn de eerste en laatste rij verwijderd, omdat ze slechts twee niet-nulwaarden bevatten.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "mCcxLGyUgRsG"
|
|
},
|
|
"source": [
|
|
"### Nullwaarden invullen\n",
|
|
"\n",
|
|
"Het kan soms logisch zijn om ontbrekende waarden in te vullen met waarden die geldig zouden kunnen zijn. Er zijn een paar technieken om nullwaarden in te vullen. De eerste is het gebruik van Domeinkennis (kennis van het onderwerp waarop de dataset is gebaseerd) om op een of andere manier de ontbrekende waarden te benaderen.\n",
|
|
"\n",
|
|
"Je kunt `isnull` gebruiken om dit direct te doen, maar dat kan tijdrovend zijn, vooral als je veel waarden moet invullen. Omdat dit een veelvoorkomende taak is in data science, biedt pandas `fillna`, waarmee je een kopie van de `Series` of `DataFrame` krijgt waarin de ontbrekende waarden zijn vervangen door een waarde naar keuze. Laten we een ander voorbeeld van een `Series` maken om te zien hoe dit in de praktijk werkt.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "CE8S7louLezV"
|
|
},
|
|
"source": [
|
|
"### Categorische gegevens (Niet-numeriek)\n",
|
|
"Laten we eerst niet-numerieke gegevens bekijken. In datasets hebben we kolommen met categorische gegevens, zoals geslacht, waar of onwaar, enz.\n",
|
|
"\n",
|
|
"In de meeste gevallen vervangen we ontbrekende waarden door de `modus` van de kolom. Stel dat we 100 datapunten hebben, waarvan 90 \"waar\" hebben aangegeven, 8 \"onwaar\" en 2 niets hebben ingevuld. Dan kunnen we de 2 invullen met \"waar\", rekening houdend met de hele kolom.\n",
|
|
"\n",
|
|
"Ook hier kunnen we domeinkennis gebruiken. Laten we een voorbeeld bekijken van invullen met de modus.\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": [
|
|
"Laten we eerst de modus vinden voordat we de `None`-waarde vullen met de modus.\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": [
|
|
"Dus, we zullen None vervangen door 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": [
|
|
"Zoals we kunnen zien, is de null-waarde vervangen. Het is vanzelfsprekend dat we alles hadden kunnen schrijven in plaats van `'True'` en het zou zijn vervangen.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "heYe1I0dOmQ_"
|
|
},
|
|
"source": [
|
|
"### Numerieke Gegevens\n",
|
|
"Nu gaan we verder met numerieke gegevens. Hier zijn twee veelgebruikte methoden om ontbrekende waarden te vervangen:\n",
|
|
"\n",
|
|
"1. Vervangen door de mediaan van de rij\n",
|
|
"2. Vervangen door het gemiddelde van de rij\n",
|
|
"\n",
|
|
"We vervangen door de mediaan in het geval van scheve gegevens met uitschieters. Dit komt omdat de mediaan robuust is tegen uitschieters.\n",
|
|
"\n",
|
|
"Wanneer de gegevens genormaliseerd zijn, kunnen we het gemiddelde gebruiken, omdat in dat geval het gemiddelde en de mediaan dicht bij elkaar liggen.\n",
|
|
"\n",
|
|
"Laten we eerst een kolom nemen die normaal verdeeld is en de ontbrekende waarde invullen met het gemiddelde van de kolom.\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": [
|
|
"Het gemiddelde van de kolom is\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": [
|
|
"Vullen met gemiddelde\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": [
|
|
"Zoals we kunnen zien, is de ontbrekende waarde vervangen door het gemiddelde.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "jIvF13a1i00Z"
|
|
},
|
|
"source": [
|
|
"Laten we nu een andere dataframe proberen, en deze keer zullen we de None-waarden vervangen door de mediaan van de kolom.\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": [
|
|
"De mediaan van de tweede kolom is\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": [
|
|
"Vullen met mediaan\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": [
|
|
"Zoals we kunnen zien, is de NaN-waarde vervangen door de mediaan van de kolom\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": [
|
|
"Je kunt alle lege invoervelden vullen met een enkele waarde, zoals `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": [
|
|
"> Belangrijke punten:\n",
|
|
"1. Het invullen van ontbrekende waarden moet worden gedaan wanneer er weinig gegevens zijn of wanneer er een strategie is om de ontbrekende gegevens in te vullen.\n",
|
|
"2. Domeinkennis kan worden gebruikt om ontbrekende waarden te benaderen en in te vullen.\n",
|
|
"3. Voor categorische gegevens worden ontbrekende waarden meestal vervangen door de modus van de kolom.\n",
|
|
"4. Voor numerieke gegevens worden ontbrekende waarden meestal ingevuld met het gemiddelde (voor genormaliseerde datasets) of de mediaan van de kolommen.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "FI9MmqFJgRsH"
|
|
},
|
|
"source": [
|
|
"### Oefening:\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": [
|
|
"Je kunt **forward-fill** nullwaarden, wat betekent dat je de laatste geldige waarde gebruikt om een nullwaarde in te vullen:\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": [
|
|
"Je kunt ook **back-fill** gebruiken om de volgende geldige waarde achterwaarts te propageren om een null te vullen:\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": [
|
|
"Zoals je misschien kunt raden, werkt dit hetzelfde met DataFrames, maar je kunt ook een `as` specificeren langs welke null-waarden moeten worden ingevuld:\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": [
|
|
"Merk op dat wanneer een eerdere waarde niet beschikbaar is voor forward-filling, de null-waarde blijft.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "eeAoOU0RgRsJ"
|
|
},
|
|
"source": [
|
|
"### Oefening:\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": [
|
|
"Je kunt creatief zijn met hoe je `fillna` gebruikt. Laten we bijvoorbeeld nog eens naar `example4` kijken, maar deze keer vullen we de ontbrekende waarden in met het gemiddelde van alle waarden in de `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": [
|
|
"Merk op dat kolom 3 nog steeds geen waarde heeft: de standaardrichting is om waarden rij per rij in te vullen.\n",
|
|
"\n",
|
|
"> **Belangrijk punt:** Er zijn meerdere manieren om om te gaan met ontbrekende waarden in je datasets. De specifieke strategie die je kiest (verwijderen, vervangen, of zelfs hoe je ze vervangt) moet worden bepaald door de specifieke kenmerken van die data. Hoe meer je met datasets werkt en interactie hebt, hoe beter je gevoel wordt voor het omgaan met ontbrekende waarden.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "bauDnESIl9FH"
|
|
},
|
|
"source": [
|
|
"### Coderen van Categorische Gegevens\n",
|
|
"\n",
|
|
"Machine learning-modellen werken alleen met cijfers en elke vorm van numerieke data. Ze kunnen geen onderscheid maken tussen een Ja en een Nee, maar wel tussen 0 en 1. Dus, nadat we de ontbrekende waarden hebben ingevuld, moeten we de categorische gegevens coderen naar een numerieke vorm zodat het model ze kan begrijpen.\n",
|
|
"\n",
|
|
"Coderen kan op twee manieren worden gedaan. We zullen deze hierna bespreken.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "uDq9SxB7mu5i"
|
|
},
|
|
"source": [
|
|
"**LABELCODERING**\n",
|
|
"\n",
|
|
"Labelcodering houdt in dat elke categorie wordt omgezet in een nummer. Stel bijvoorbeeld dat we een dataset hebben van vliegtuigpassagiers en er is een kolom met hun klasse, zoals ['business class', 'economy class', 'first class']. Als hier labelcodering op wordt toegepast, wordt dit omgezet naar [0, 1, 2]. Laten we een voorbeeld bekijken via code. Omdat we `scikit-learn` in de komende notebooks gaan leren, gebruiken we het hier niet.\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": [
|
|
"Om label encoding uit te voeren op de 1e kolom, moeten we eerst een mapping beschrijven van elke klasse naar een nummer, voordat we vervangen.\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": [
|
|
"Zoals we kunnen zien, komt de output overeen met wat we hadden verwacht. Dus, wanneer gebruiken we label encoding? Label encoding wordt gebruikt in een of beide van de volgende gevallen:\n",
|
|
"1. Wanneer het aantal categorieën groot is\n",
|
|
"2. Wanneer de categorieën een volgorde hebben.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "eQPAPVwsqWT7"
|
|
},
|
|
"source": [
|
|
"**ONE HOT ENCODING**\n",
|
|
"\n",
|
|
"Een andere vorm van codering is One Hot Encoding. Bij deze vorm van codering wordt elke categorie van de kolom toegevoegd als een aparte kolom, en elk datapunt krijgt een 0 of een 1 afhankelijk van of het die categorie bevat. Dus, als er n verschillende categorieën zijn, worden er n kolommen toegevoegd aan de dataframe.\n",
|
|
"\n",
|
|
"Bijvoorbeeld, laten we hetzelfde voorbeeld van vliegtuigklassen nemen. De categorieën waren: ['business class', 'economy class', 'first class']. Als we One Hot Encoding toepassen, worden de volgende drie kolommen toegevoegd aan de dataset: ['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": [
|
|
"Laten we one-hot encoding uitvoeren op de eerste kolom\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": [
|
|
"Elke one-hot-gecodeerde kolom bevat 0 of 1, wat aangeeft of die categorie bestaat voor dat datapunt.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "bDnC4NQOu0qr"
|
|
},
|
|
"source": [
|
|
"Wanneer gebruiken we one-hot encoding? One-hot encoding wordt gebruikt in een of beide van de volgende gevallen:\n",
|
|
"\n",
|
|
"1. Wanneer het aantal categorieën en de grootte van de dataset klein zijn.\n",
|
|
"2. Wanneer de categorieën geen specifieke volgorde hebben.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "XnUmci_4uvyu"
|
|
},
|
|
"source": [
|
|
"> Belangrijkste punten:\n",
|
|
"1. Codering wordt gebruikt om niet-numerieke gegevens om te zetten in numerieke gegevens.\n",
|
|
"2. Er zijn twee soorten codering: Labelcodering en One Hot-codering, die beide kunnen worden uitgevoerd afhankelijk van de eisen van de dataset.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "K8UXOJYRgRsJ"
|
|
},
|
|
"source": [
|
|
"## Duplicaatgegevens verwijderen\n",
|
|
"\n",
|
|
"> **Leerdoel:** Aan het einde van deze subsectie moet je in staat zijn om duplicaatwaarden in DataFrames te identificeren en te verwijderen.\n",
|
|
"\n",
|
|
"Naast ontbrekende gegevens kom je vaak duplicaatgegevens tegen in datasets uit de praktijk. Gelukkig biedt pandas een eenvoudige manier om duplicaatvermeldingen te detecteren en te verwijderen.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "qrEG-Wa0gRsJ"
|
|
},
|
|
"source": [
|
|
"### Duplicaten identificeren: `duplicated`\n",
|
|
"\n",
|
|
"Je kunt eenvoudig dubbele waarden opsporen met de `duplicated`-methode in pandas, die een Booleaanse maskering retourneert om aan te geven of een invoer in een `DataFrame` een duplicaat is van een eerdere. Laten we een ander voorbeeld `DataFrame` maken om dit in actie te zien.\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": [
|
|
"### Duplicaten verwijderen: `drop_duplicates`\n",
|
|
"`drop_duplicates` geeft eenvoudigweg een kopie van de gegevens terug waarvoor alle `duplicated` waarden `False` zijn:\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": [
|
|
"Zowel `duplicated` als `drop_duplicates` beschouwen standaard alle kolommen, maar je kunt specificeren dat ze alleen een subset van kolommen in je `DataFrame` onderzoeken:\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": [
|
|
"> **Belangrijk:** Het verwijderen van dubbele gegevens is een essentieel onderdeel van bijna elk data-scienceproject. Dubbele gegevens kunnen de resultaten van je analyses veranderen en je onnauwkeurige resultaten geven!\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Kwaliteitscontroles van gegevens uit de praktijk\n",
|
|
"\n",
|
|
"> **Leerdoel:** Aan het einde van deze sectie moet je in staat zijn om veelvoorkomende kwaliteitsproblemen in gegevens uit de praktijk te herkennen en te corrigeren, zoals inconsistente categoriewaarden, abnormale numerieke waarden (uitbijters) en dubbele entiteiten met variaties.\n",
|
|
"\n",
|
|
"Hoewel ontbrekende waarden en exacte duplicaten veelvoorkomende problemen zijn, bevatten datasets uit de praktijk vaak subtielere problemen:\n",
|
|
"\n",
|
|
"1. **Inconsistente categoriewaarden**: Dezelfde categorie anders gespeld (bijv. \"USA\", \"U.S.A\", \"United States\")\n",
|
|
"2. **Abnormale numerieke waarden**: Extreme uitbijters die wijzen op invoerfouten (bijv. leeftijd = 999)\n",
|
|
"3. **Bijna-duplicaten**: Records die dezelfde entiteit vertegenwoordigen met kleine variaties\n",
|
|
"\n",
|
|
"Laten we technieken verkennen om deze problemen te detecteren en aan te pakken.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Een voorbeeld van een \"vuile\" dataset maken\n",
|
|
"\n",
|
|
"Laten we eerst een voorbeelddataset maken die de soorten problemen bevat die we vaak tegenkomen in echte data:\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. Detecteren van inconsistente categorische waarden\n",
|
|
"\n",
|
|
"Let op dat de `country`-kolom meerdere representaties heeft voor dezelfde landen. Laten we deze inconsistenties identificeren:\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": [
|
|
"#### Standaardiseren van Categorische Waarden\n",
|
|
"\n",
|
|
"We kunnen een mapping maken om deze waarden te standaardiseren. Een eenvoudige aanpak is om ze om te zetten naar kleine letters en een mapping dictionary te maken:\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": [
|
|
"**Alternatief: Gebruik van fuzzy matching**\n",
|
|
"\n",
|
|
"Voor meer complexe gevallen kunnen we fuzzy string matching gebruiken met de `rapidfuzz`-bibliotheek om automatisch vergelijkbare strings te detecteren:\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. Detecteren van Abnormale Numerieke Waarden (Uitbijters)\n",
|
|
"\n",
|
|
"Als we naar de `age`-kolom kijken, zien we enkele verdachte waarden zoals 199 en -5. Laten we statistische methoden gebruiken om deze uitbijters te detecteren.\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": [
|
|
"#### Gebruik van de IQR (Interkwartielafstand) Methode\n",
|
|
"\n",
|
|
"De IQR-methode is een robuuste statistische techniek voor het detecteren van uitschieters die minder gevoelig is voor extreme waarden:\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": [
|
|
"#### Gebruik van de Z-Score Methode\n",
|
|
"\n",
|
|
"De Z-score methode identificeert uitschieters op basis van standaarddeviaties vanaf het gemiddelde:\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": [
|
|
"#### Omgaan met uitschieters\n",
|
|
"\n",
|
|
"Zodra uitschieters zijn gedetecteerd, kunnen ze op verschillende manieren worden behandeld:\n",
|
|
"1. **Verwijderen**: Verwijder rijen met uitschieters (als het fouten zijn)\n",
|
|
"2. **Afschermen**: Vervang door grenswaarden\n",
|
|
"3. **Vervangen door NaN**: Behandel als ontbrekende gegevens en gebruik imputatietechnieken\n",
|
|
"4. **Behouden**: Als het legitieme extreme waarden zijn\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. Detecteren van bijna-duplicaat rijen\n",
|
|
"\n",
|
|
"Merk op dat onze dataset meerdere vermeldingen heeft voor \"John Smith\" met licht verschillende waarden. Laten we potentiële duplicaten identificeren op basis van naamgelijkenis.\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": [
|
|
"#### Nabijgelegen duplicaten vinden met fuzzy matching\n",
|
|
"\n",
|
|
"Voor meer geavanceerde duplicaatdetectie kunnen we fuzzy matching gebruiken om vergelijkbare namen te vinden:\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": [
|
|
"#### Omgaan met duplicaten\n",
|
|
"\n",
|
|
"Zodra ze zijn geïdentificeerd, moet je beslissen hoe je met duplicaten omgaat:\n",
|
|
"1. **Behoud de eerste voorkoming**: Gebruik `drop_duplicates(keep='first')`\n",
|
|
"2. **Behoud de laatste voorkoming**: Gebruik `drop_duplicates(keep='last')`\n",
|
|
"3. **Informatie samenvoegen**: Combineer informatie uit dubbele rijen\n",
|
|
"4. **Handmatige controle**: Markeer voor menselijke beoordeling\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": [
|
|
"### Samenvatting: Volledige Gegevensopschoonpipeline\n",
|
|
"\n",
|
|
"Laten we alles samenvoegen tot een uitgebreide opschoonpipeline:\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": [
|
|
"### 🎯 Uitdagingsoefening\n",
|
|
"\n",
|
|
"Nu is het jouw beurt! Hieronder staat een nieuwe rij met gegevens die meerdere kwaliteitsproblemen bevat. Kun je:\n",
|
|
"\n",
|
|
"1. Alle problemen in deze rij identificeren\n",
|
|
"2. Code schrijven om elk probleem op te lossen\n",
|
|
"3. De schoongemaakte rij toevoegen aan de dataset\n",
|
|
"\n",
|
|
"Hier zijn de problematische gegevens:\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": [
|
|
"### Belangrijke punten\n",
|
|
"\n",
|
|
"1. **Inconsistente categorieën** komen vaak voor in echte datasets. Controleer altijd de unieke waarden en standaardiseer ze met behulp van mappings of fuzzy matching.\n",
|
|
"\n",
|
|
"2. **Uitschieters** kunnen je analyse aanzienlijk beïnvloeden. Gebruik domeinkennis in combinatie met statistische methoden (IQR, Z-score) om ze te detecteren.\n",
|
|
"\n",
|
|
"3. **Bijna-duplicaten** zijn moeilijker te herkennen dan exacte duplicaten. Overweeg het gebruik van fuzzy matching en het normaliseren van gegevens (kleine letters, spaties verwijderen) om ze te identificeren.\n",
|
|
"\n",
|
|
"4. **Gegevens opschonen is iteratief**. Je moet mogelijk meerdere technieken toepassen en de resultaten beoordelen voordat je je opgeschoonde dataset definitief maakt.\n",
|
|
"\n",
|
|
"5. **Documenteer je beslissingen**. Houd bij welke schoonmaakstappen je hebt toegepast en waarom, omdat dit belangrijk is voor reproduceerbaarheid en transparantie.\n",
|
|
"\n",
|
|
"> **Beste praktijk:** Bewaar altijd een kopie van je originele \"vuile\" data. Overschrijf nooit je bronbestanden - maak opgeschoonde versies met duidelijke naamconventies zoals `data_cleaned.csv`.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n---\n\n**Disclaimer**: \nDit document is vertaald met behulp van de AI-vertalingsservice [Co-op Translator](https://github.com/Azure/co-op-translator). Hoewel we streven naar nauwkeurigheid, dient u zich ervan bewust te zijn dat geautomatiseerde vertalingen fouten of onnauwkeurigheden kunnen bevatten. Het originele document in de oorspronkelijke taal moet worden beschouwd als de gezaghebbende bron. Voor cruciale informatie wordt professionele menselijke vertaling aanbevolen. Wij zijn niet aansprakelijk voor misverstanden of verkeerde interpretaties die voortvloeien uit het gebruik van deze vertaling.\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:29:48+00:00",
|
|
"source_file": "2-Working-With-Data/08-data-preparation/notebook.ipynb",
|
|
"language_code": "nl"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 0
|
|
} |