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.
Data-Science-For-Beginners/translations/el/2-Working-With-Data/08-data-preparation/notebook.ipynb

4241 lines
148 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "rQ8UhzFpgRra"
},
"source": [
"# Προετοιμασία Δεδομένων\n",
"\n",
"[Αρχική πηγή Notebook από *Data Science: Introduction to Machine Learning for Data Science Python and Machine Learning Studio by Lee Stott*](https://github.com/leestott/intro-Datascience/blob/master/Course%20Materials/4-Cleaning_and_Manipulating-Reference.ipynb)\n",
"\n",
"## Εξερεύνηση πληροφοριών του `DataFrame`\n",
"\n",
"> **Στόχος μάθησης:** Μέχρι το τέλος αυτής της υποενότητας, θα πρέπει να είστε άνετοι με την εύρεση γενικών πληροφοριών για τα δεδομένα που είναι αποθηκευμένα σε pandas DataFrames.\n",
"\n",
"Μόλις φορτώσετε τα δεδομένα σας στο pandas, είναι πολύ πιθανό να βρίσκονται σε ένα `DataFrame`. Ωστόσο, αν το σύνολο δεδομένων στο `DataFrame` σας έχει 60.000 γραμμές και 400 στήλες, πώς μπορείτε καν να αρχίσετε να κατανοείτε με τι δουλεύετε; Ευτυχώς, το pandas παρέχει μερικά βολικά εργαλεία για να δείτε γρήγορα συνολικές πληροφορίες για ένα `DataFrame`, καθώς και τις πρώτες και τελευταίες γραμμές.\n",
"\n",
"Για να εξερευνήσουμε αυτή τη λειτουργικότητα, θα εισάγουμε τη βιβλιοθήκη Python scikit-learn και θα χρησιμοποιήσουμε ένα εμβληματικό σύνολο δεδομένων που κάθε επιστήμονας δεδομένων έχει δει εκατοντάδες φορές: το σύνολο δεδομένων *Iris* του Βρετανού βιολόγου Ronald Fisher, που χρησιμοποιήθηκε στο άρθρο του το 1936 \"Η χρήση πολλαπλών μετρήσεων σε ταξινομικά προβλήματα\":\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",
"Έχουμε φορτώσει το Iris Dataset στη μεταβλητή `iris_df`. Πριν εξετάσουμε τα δεδομένα, θα ήταν χρήσιμο να γνωρίζουμε τον αριθμό των σημείων δεδομένων που έχουμε και το συνολικό μέγεθος του συνόλου δεδομένων. Είναι χρήσιμο να δούμε τον όγκο των δεδομένων που επεξεργαζόμαστε.\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": [
"Λοιπόν, έχουμε να κάνουμε με 150 γραμμές και 4 στήλες δεδομένων. Κάθε γραμμή αντιπροσωπεύει ένα σημείο δεδομένων και κάθε στήλη αντιπροσωπεύει ένα χαρακτηριστικό που σχετίζεται με το πλαίσιο δεδομένων. Ουσιαστικά, υπάρχουν 150 σημεία δεδομένων που περιέχουν από 4 χαρακτηριστικά το καθένα.\n",
"\n",
"Το `shape` εδώ είναι ένα χαρακτηριστικό του πλαισίου δεδομένων και όχι μια συνάρτηση, γι' αυτό δεν τελειώνει με ένα ζευγάρι παρενθέσεων.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "d3AZKs0PinGP"
},
"source": [
"### `DataFrame.columns`\n",
"Ας εξετάσουμε τώρα τις 4 στήλες δεδομένων. Τι ακριβώς αντιπροσωπεύει η κάθε μία; Η ιδιότητα `columns` θα μας δώσει τα ονόματα των στηλών στο 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": [
"Όπως μπορούμε να δούμε, υπάρχουν τέσσερις (4) στήλες. Το χαρακτηριστικό `columns` μας λέει το όνομα των στηλών και ουσιαστικά τίποτα άλλο. Αυτό το χαρακτηριστικό αποκτά σημασία όταν θέλουμε να προσδιορίσουμε τα χαρακτηριστικά που περιέχει ένα σύνολο δεδομένων.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "2UTlvkjmgRrs"
},
"source": [
"### `DataFrame.info`\n",
"Η ποσότητα των δεδομένων (που δίνεται από το χαρακτηριστικό `shape`) και τα ονόματα των χαρακτηριστικών ή στηλών (που δίνονται από το χαρακτηριστικό `columns`) μας λένε κάτι για το σύνολο δεδομένων. Τώρα, θα θέλαμε να εμβαθύνουμε περισσότερο στο σύνολο δεδομένων. Η συνάρτηση `DataFrame.info()` είναι αρκετά χρήσιμη για αυτό.\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": [
"Από εδώ, μπορούμε να κάνουμε μερικές παρατηρήσεις:\n",
"1. Ο τύπος δεδομένων κάθε στήλης: Σε αυτό το σύνολο δεδομένων, όλα τα δεδομένα αποθηκεύονται ως αριθμοί κινητής υποδιαστολής 64-bit.\n",
"2. Αριθμός μη μηδενικών τιμών: Η διαχείριση των μηδενικών τιμών είναι ένα σημαντικό βήμα στην προετοιμασία δεδομένων. Θα αντιμετωπιστεί αργότερα στο σημειωματάριο.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "IYlyxbpWFEF4"
},
"source": [
"### DataFrame.describe()\n",
"Ας υποθέσουμε ότι έχουμε πολλά αριθμητικά δεδομένα στο σύνολο δεδομένων μας. Μονομεταβλητοί στατιστικοί υπολογισμοί, όπως ο μέσος όρος, η διάμεσος, τα τεταρτημόρια κ.λπ., μπορούν να γίνουν ξεχωριστά για κάθε στήλη. Η συνάρτηση `DataFrame.describe()` μας παρέχει μια στατιστική σύνοψη των αριθμητικών στηλών ενός συνόλου δεδομένων.\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": [
"Η παραπάνω έξοδος δείχνει τον συνολικό αριθμό σημείων δεδομένων, τη μέση τιμή, την τυπική απόκλιση, την ελάχιστη τιμή, το κατώτερο τεταρτημόριο (25%), τη διάμεσο (50%), το ανώτερο τεταρτημόριο (75%) και τη μέγιστη τιμή κάθε στήλης.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "-lviAu99gRrv"
},
"source": [
"### `DataFrame.head`\n",
"Με όλες τις παραπάνω συναρτήσεις και ιδιότητες, έχουμε αποκτήσει μια συνολική εικόνα του συνόλου δεδομένων. Γνωρίζουμε πόσα σημεία δεδομένων υπάρχουν, πόσα χαρακτηριστικά υπάρχουν, τον τύπο δεδομένων κάθε χαρακτηριστικού και τον αριθμό των μη μηδενικών τιμών για κάθε χαρακτηριστικό.\n",
"\n",
"Τώρα είναι η ώρα να δούμε τα ίδια τα δεδομένα. Ας δούμε πώς φαίνονται οι πρώτες γραμμές (τα πρώτα σημεία δεδομένων) του `DataFrame` μας:\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 204
},
"id": "DZMJZh0OgRrw",
"outputId": "d9393ee5-c106-4797-f815-218f17160e00",
"trusted": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>sepal length (cm)</th>\n",
" <th>sepal width (cm)</th>\n",
" <th>petal length (cm)</th>\n",
" <th>petal width (cm)</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>5.1</td>\n",
" <td>3.5</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>4.9</td>\n",
" <td>3.0</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>4.7</td>\n",
" <td>3.2</td>\n",
" <td>1.3</td>\n",
" <td>0.2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4.6</td>\n",
" <td>3.1</td>\n",
" <td>1.5</td>\n",
" <td>0.2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>5.0</td>\n",
" <td>3.6</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)\n",
"0 5.1 3.5 1.4 0.2\n",
"1 4.9 3.0 1.4 0.2\n",
"2 4.7 3.2 1.3 0.2\n",
"3 4.6 3.1 1.5 0.2\n",
"4 5.0 3.6 1.4 0.2"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"iris_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "EBHEimZuEFQK"
},
"source": [
"Ως το αποτέλεσμα εδώ, μπορούμε να δούμε πέντε (5) εγγραφές του συνόλου δεδομένων. Αν κοιτάξουμε τον δείκτη στα αριστερά, διαπιστώνουμε ότι αυτές είναι οι πρώτες πέντε σειρές.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "oj7GkrTdgRry"
},
"source": [
"### Άσκηση:\n",
"\n",
"Από το παραπάνω παράδειγμα, είναι ξεκάθαρο ότι, από προεπιλογή, η μέθοδος `DataFrame.head` επιστρέφει τις πρώτες πέντε γραμμές ενός `DataFrame`. Στο παρακάτω κελί κώδικα, μπορείτε να βρείτε έναν τρόπο να εμφανίσετε περισσότερες από πέντε γραμμές;\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",
"Ένας άλλος τρόπος να δούμε τα δεδομένα είναι από το τέλος (αντί για την αρχή). Η αντίθετη λειτουργία του `DataFrame.head` είναι το `DataFrame.tail`, το οποίο επιστρέφει τις τελευταίες πέντε γραμμές ενός `DataFrame`:\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 0
},
"id": "heanjfGWgRr2",
"outputId": "6ae09a21-fe09-4110-b0d7-1a1fbf34d7f3",
"trusted": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>sepal length (cm)</th>\n",
" <th>sepal width (cm)</th>\n",
" <th>petal length (cm)</th>\n",
" <th>petal width (cm)</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>145</th>\n",
" <td>6.7</td>\n",
" <td>3.0</td>\n",
" <td>5.2</td>\n",
" <td>2.3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>146</th>\n",
" <td>6.3</td>\n",
" <td>2.5</td>\n",
" <td>5.0</td>\n",
" <td>1.9</td>\n",
" </tr>\n",
" <tr>\n",
" <th>147</th>\n",
" <td>6.5</td>\n",
" <td>3.0</td>\n",
" <td>5.2</td>\n",
" <td>2.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>148</th>\n",
" <td>6.2</td>\n",
" <td>3.4</td>\n",
" <td>5.4</td>\n",
" <td>2.3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>149</th>\n",
" <td>5.9</td>\n",
" <td>3.0</td>\n",
" <td>5.1</td>\n",
" <td>1.8</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)\n",
"145 6.7 3.0 5.2 2.3\n",
"146 6.3 2.5 5.0 1.9\n",
"147 6.5 3.0 5.2 2.0\n",
"148 6.2 3.4 5.4 2.3\n",
"149 5.9 3.0 5.1 1.8"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"iris_df.tail()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "31kBWfyLgRr3"
},
"source": [
"Στην πράξη, είναι χρήσιμο να μπορείτε να εξετάσετε εύκολα τις πρώτες ή τις τελευταίες γραμμές ενός `DataFrame`, ιδιαίτερα όταν ψάχνετε για ακραίες τιμές σε ταξινομημένα σύνολα δεδομένων.\n",
"\n",
"Όλες οι συναρτήσεις και οι ιδιότητες που παρουσιάστηκαν παραπάνω με τη βοήθεια παραδειγμάτων κώδικα, μας βοηθούν να αποκτήσουμε μια εικόνα και αίσθηση των δεδομένων.\n",
"\n",
"> **Συμπέρασμα:** Ακόμα και μόνο κοιτάζοντας τα μεταδεδομένα σχετικά με τις πληροφορίες σε ένα DataFrame ή τις πρώτες και τελευταίες τιμές του, μπορείτε να αποκτήσετε άμεσα μια ιδέα για το μέγεθος, τη μορφή και το περιεχόμενο των δεδομένων που επεξεργάζεστε.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "TvurZyLSDxq_"
},
"source": [
"### Ελλιπή Δεδομένα\n",
"Ας εξετάσουμε τα ελλιπή δεδομένα. Ελλιπή δεδομένα εμφανίζονται όταν δεν έχει αποθηκευτεί κάποια τιμή σε ορισμένες στήλες.\n",
"\n",
"Ας πάρουμε ένα παράδειγμα: ας πούμε ότι κάποιος είναι ευαίσθητος σχετικά με το βάρος του και δεν συμπληρώνει το πεδίο του βάρους σε μια έρευνα. Τότε, η τιμή του βάρους για αυτό το άτομο θα λείπει.\n",
"\n",
"Τις περισσότερες φορές, σε σύνολα δεδομένων του πραγματικού κόσμου, εμφανίζονται ελλιπείς τιμές.\n",
"\n",
"**Πώς το Pandas διαχειρίζεται τα ελλιπή δεδομένα**\n",
"\n",
"Το Pandas διαχειρίζεται τις ελλιπείς τιμές με δύο τρόπους. Ο πρώτος τρόπος, τον οποίο έχετε δει σε προηγούμενες ενότητες, είναι το `NaN`, ή Not a Number. Αυτό είναι στην πραγματικότητα μια ειδική τιμή που αποτελεί μέρος της προδιαγραφής IEEE floating-point και χρησιμοποιείται μόνο για να υποδείξει ελλιπείς τιμές κινητής υποδιαστολής.\n",
"\n",
"Για ελλιπείς τιμές εκτός από αριθμούς κινητής υποδιαστολής, το Pandas χρησιμοποιεί το αντικείμενο `None` της Python. Παρόλο που μπορεί να φαίνεται μπερδεμένο ότι θα συναντήσετε δύο διαφορετικά είδη τιμών που ουσιαστικά λένε το ίδιο πράγμα, υπάρχουν βάσιμοι προγραμματιστικοί λόγοι για αυτήν την επιλογή σχεδίασης και, στην πράξη, αυτή η προσέγγιση επιτρέπει στο Pandas να προσφέρει έναν καλό συμβιβασμό για τη συντριπτική πλειονότητα των περιπτώσεων. Παρ' όλα αυτά, τόσο το `None` όσο και το `NaN` έχουν περιορισμούς που πρέπει να έχετε υπόψη σας σχετικά με το πώς μπορούν να χρησιμοποιηθούν.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "lOHqUlZFgRr5"
},
"source": [
"### `None`: μη αριθμητικά δεδομένα που λείπουν\n",
"Επειδή το `None` προέρχεται από την Python, δεν μπορεί να χρησιμοποιηθεί σε πίνακες NumPy και pandas που δεν έχουν τύπο δεδομένων `'object'`. Θυμηθείτε, οι πίνακες NumPy (και οι δομές δεδομένων στις pandas) μπορούν να περιέχουν μόνο έναν τύπο δεδομένων. Αυτό είναι που τους δίνει τη μεγάλη τους δύναμη για επεξεργασία δεδομένων μεγάλης κλίμακας και υπολογιστική εργασία, αλλά περιορίζει επίσης την ευελιξία τους. Τέτοιοι πίνακες πρέπει να μετατρέπονται στον \"χαμηλότερο κοινό παρονομαστή\", δηλαδή τον τύπο δεδομένων που θα περιλαμβάνει όλα τα στοιχεία του πίνακα. Όταν το `None` βρίσκεται στον πίνακα, σημαίνει ότι εργάζεστε με αντικείμενα της Python.\n",
"\n",
"Για να το δείτε στην πράξη, εξετάστε τον παρακάτω παράδειγμα πίνακα (προσέξτε το `dtype` του):\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "QIoNdY4ngRr7",
"outputId": "92779f18-62f4-4a03-eca2-e9a101604336",
"trusted": false
},
"outputs": [
{
"data": {
"text/plain": [
"array([2, None, 6, 8], dtype=object)"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import numpy as np\n",
"\n",
"example1 = np.array([2, None, 6, 8])\n",
"example1"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "pdlgPNbhgRr7"
},
"source": [
"Η πραγματικότητα των ανυψωμένων τύπων δεδομένων συνοδεύεται από δύο παρενέργειες. Πρώτον, οι λειτουργίες θα εκτελούνται στο επίπεδο του ερμηνευμένου κώδικα Python αντί για τον μεταγλωττισμένο κώδικα NumPy. Ουσιαστικά, αυτό σημαίνει ότι οποιεσδήποτε λειτουργίες που περιλαμβάνουν `Series` ή `DataFrames` με `None` θα είναι πιο αργές. Αν και πιθανότατα δεν θα παρατηρήσετε αυτήν την πτώση απόδοσης, για μεγάλα σύνολα δεδομένων μπορεί να γίνει πρόβλημα.\n",
"\n",
"Η δεύτερη παρενέργεια προκύπτει από την πρώτη. Επειδή το `None` ουσιαστικά \"τραβάει\" τα `Series` ή τα `DataFrame` πίσω στον κόσμο της απλής Python, η χρήση συναθροίσεων NumPy/pandas όπως `sum()` ή `min()` σε πίνακες που περιέχουν μια τιμή ``None`` θα παράγει γενικά ένα σφάλμα:\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": [
"**Κύριο συμπέρασμα**: Η πρόσθεση (και άλλες πράξεις) μεταξύ ακέραιων αριθμών και τιμών `None` είναι απροσδιόριστη, κάτι που μπορεί να περιορίσει τις δυνατότητες επεξεργασίας συνόλων δεδομένων που τις περιέχουν.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "pWvVHvETgRr9"
},
"source": [
"### `NaN`: έλλειψη τιμών float\n",
"\n",
"Σε αντίθεση με το `None`, το NumPy (και κατά συνέπεια το pandas) υποστηρίζει το `NaN` για τις γρήγορες, διανυσματικές λειτουργίες και ufuncs. Το αρνητικό είναι ότι οποιαδήποτε αριθμητική πράξη που εκτελείται με `NaN` πάντα καταλήγει σε `NaN`. Για παράδειγμα:\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": [
"Τα καλά νέα: οι συναθροίσεις που εκτελούνται σε πίνακες με `NaN` μέσα τους δεν εμφανίζουν σφάλματα. Τα κακά νέα: τα αποτελέσματα δεν είναι ομοιόμορφα χρήσιμα:\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": [
"### Άσκηση:\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": [
"Θυμήσου: `NaN` είναι μόνο για ελλείποντα δεκαδικά (floating-point) δεδομένα· δεν υπάρχει αντίστοιχο `NaN` για ακέραιους, συμβολοσειρές ή λογικές τιμές.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "kj6EKdsAgRsA"
},
"source": [
"### `NaN` και `None`: τιμές null στο pandas\n",
"\n",
"Παρόλο που το `NaN` και το `None` μπορεί να συμπεριφέρονται κάπως διαφορετικά, το pandas έχει σχεδιαστεί ώστε να τα χειρίζεται εναλλακτικά. Για να καταλάβετε τι εννοούμε, σκεφτείτε μια `Series` από ακέραιους αριθμούς:\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": [
"### Άσκηση:\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": [
"Κατά τη διαδικασία αναβάθμισης τύπων δεδομένων για την καθιέρωση ομοιογένειας δεδομένων σε `Series` και `DataFrame`s, το pandas μπορεί να αλλάξει πρόθυμα τις ελλείπουσες τιμές μεταξύ `None` και `NaN`. Λόγω αυτής της σχεδιαστικής λειτουργίας, είναι χρήσιμο να σκεφτόμαστε το `None` και το `NaN` ως δύο διαφορετικές μορφές \"κενών\" στο pandas. Πράγματι, ορισμένες από τις βασικές μεθόδους που θα χρησιμοποιήσετε για να διαχειριστείτε ελλείπουσες τιμές στο pandas αντικατοπτρίζουν αυτήν την ιδέα στα ονόματά τους:\n",
"\n",
"- `isnull()`: Δημιουργεί μια μάσκα Boolean που υποδεικνύει τις ελλείπουσες τιμές\n",
"- `notnull()`: Αντίθετο του `isnull()`\n",
"- `dropna()`: Επιστρέφει μια φιλτραρισμένη έκδοση των δεδομένων\n",
"- `fillna()`: Επιστρέφει ένα αντίγραφο των δεδομένων με τις ελλείπουσες τιμές συμπληρωμένες ή υπολογισμένες\n",
"\n",
"Αυτές είναι σημαντικές μέθοδοι που πρέπει να μάθετε και να εξοικειωθείτε, οπότε ας τις εξετάσουμε καθεμία πιο αναλυτικά.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Yh5ifd9FgRsB"
},
"source": [
"### Εντοπισμός κενών τιμών\n",
"\n",
"Τώρα που έχουμε κατανοήσει τη σημασία των ελλειπόντων τιμών, πρέπει να τις εντοπίσουμε στο σύνολο δεδομένων μας, πριν τις διαχειριστούμε. \n",
"Οι μέθοδοι `isnull()` και `notnull()` είναι οι κύριες μέθοδοι σας για τον εντοπισμό κενών δεδομένων. Και οι δύο επιστρέφουν μάσκες Boolean πάνω στα δεδομένα σας.\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": [
"Κοιτάξτε προσεκτικά το αποτέλεσμα. Σας εκπλήσσει κάτι από αυτό; Παρόλο που το `0` είναι μια αριθμητική τιμή null, παραμένει ένας απολύτως καλός ακέραιος αριθμός και το pandas το αντιμετωπίζει ως τέτοιο. Το `''` είναι λίγο πιο λεπτό. Ενώ το χρησιμοποιήσαμε στην Ενότητα 1 για να εκπροσωπήσουμε μια κενή συμβολοσειρά, παραμένει ένα αντικείμενο συμβολοσειράς και όχι μια αναπαράσταση του null σύμφωνα με το pandas.\n",
"\n",
"Τώρα, ας το δούμε από την αντίθετη πλευρά και ας χρησιμοποιήσουμε αυτές τις μεθόδους με τρόπο που μοιάζει περισσότερο με τον τρόπο που θα τις χρησιμοποιείτε στην πράξη. Μπορείτε να χρησιμοποιήσετε Boolean μάσκες απευθείας ως δείκτη ``Series`` ή ``DataFrame``, κάτι που μπορεί να είναι χρήσιμο όταν προσπαθείτε να εργαστείτε με απομονωμένες τιμές που λείπουν (ή που υπάρχουν).\n",
"\n",
"Αν θέλουμε τον συνολικό αριθμό των τιμών που λείπουν, μπορούμε απλώς να κάνουμε ένα άθροισμα πάνω στη μάσκα που παράγεται από τη μέθοδο `isnull()`.\n"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "JCcQVoPkHDUv",
"outputId": "001daa72-54f8-4bd5-842a-4df627a79d4d"
},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"example3.isnull().sum()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "PlBqEo3mgRsC"
},
"source": [
"### Άσκηση:\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": [
"**Βασικό συμπέρασμα**: Τόσο οι μέθοδοι `isnull()` όσο και `notnull()` παράγουν παρόμοια αποτελέσματα όταν τις χρησιμοποιείτε σε DataFrames: δείχνουν τα αποτελέσματα και τον δείκτη αυτών των αποτελεσμάτων, κάτι που θα σας βοηθήσει σημαντικά καθώς επεξεργάζεστε τα δεδομένα σας.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "BvnoojWsgRr4"
},
"source": [
"### Αντιμετώπιση ελλιπών δεδομένων\n",
"\n",
"> **Στόχος μάθησης:** Μέχρι το τέλος αυτής της υποενότητας, θα πρέπει να γνωρίζετε πώς και πότε να αντικαθιστάτε ή να αφαιρείτε κενές τιμές από DataFrames.\n",
"\n",
"Τα μοντέλα Μηχανικής Μάθησης δεν μπορούν να επεξεργαστούν μόνα τους ελλιπή δεδομένα. Επομένως, πριν περάσουμε τα δεδομένα στο μοντέλο, πρέπει να αντιμετωπίσουμε αυτές τις ελλείψεις.\n",
"\n",
"Ο τρόπος με τον οποίο χειριζόμαστε τα ελλιπή δεδομένα περιλαμβάνει λεπτές συμβιβαστικές αποφάσεις, που μπορούν να επηρεάσουν την τελική ανάλυση και τα αποτελέσματα στον πραγματικό κόσμο.\n",
"\n",
"Υπάρχουν κυρίως δύο τρόποι αντιμετώπισης ελλιπών δεδομένων:\n",
"\n",
"1. Διαγραφή της γραμμής που περιέχει την ελλιπή τιμή\n",
"2. Αντικατάσταση της ελλιπούς τιμής με κάποια άλλη τιμή\n",
"\n",
"Θα συζητήσουμε και τις δύο αυτές μεθόδους καθώς και τα πλεονεκτήματα και μειονεκτήματά τους λεπτομερώς.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3VaYC1TvgRsD"
},
"source": [
"### Αφαίρεση κενών τιμών\n",
"\n",
"Η ποσότητα των δεδομένων που περνάμε στο μοντέλο μας έχει άμεση επίδραση στην απόδοσή του. Η αφαίρεση κενών τιμών σημαίνει ότι μειώνουμε τον αριθμό των σημείων δεδομένων και, κατά συνέπεια, το μέγεθος του συνόλου δεδομένων. Επομένως, είναι προτιμότερο να αφαιρούμε γραμμές με κενές τιμές όταν το σύνολο δεδομένων είναι αρκετά μεγάλο.\n",
"\n",
"Μια άλλη περίπτωση μπορεί να είναι ότι μια συγκεκριμένη γραμμή ή στήλη έχει πολλές ελλείπουσες τιμές. Σε αυτή την περίπτωση, μπορεί να αφαιρεθούν, καθώς δεν θα προσθέσουν ιδιαίτερη αξία στην ανάλυσή μας, αφού τα περισσότερα δεδομένα λείπουν για αυτή τη γραμμή/στήλη.\n",
"\n",
"Πέρα από την αναγνώριση ελλειπουσών τιμών, το pandas παρέχει έναν εύχρηστο τρόπο για την αφαίρεση κενών τιμών από `Series` και `DataFrame`s. Για να το δούμε στην πράξη, ας επιστρέψουμε στο `example3`. Η συνάρτηση `DataFrame.dropna()` βοηθά στην αφαίρεση των γραμμών με κενές τιμές.\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": [
"Σημειώστε ότι αυτό θα πρέπει να μοιάζει με το αποτέλεσμα από `example3[example3.notnull()]`. Η διαφορά εδώ είναι ότι, αντί απλώς να γίνεται ευρετηρίαση στις τιμές που έχουν μάσκα, το `dropna` έχει αφαιρέσει αυτές τις ελλείπουσες τιμές από το `Series` `example3`.\n",
"\n",
"Επειδή τα DataFrames έχουν δύο διαστάσεις, προσφέρουν περισσότερες επιλογές για την αφαίρεση δεδομένων.\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": [
"(Παρατηρήσατε ότι το pandas ανέβασε δύο από τις στήλες σε τύπο float για να φιλοξενήσει τα `NaN`;)\n",
"\n",
"Δεν μπορείτε να αφαιρέσετε μία μόνο τιμή από ένα `DataFrame`, οπότε πρέπει να αφαιρέσετε ολόκληρες γραμμές ή στήλες. Ανάλογα με το τι κάνετε, μπορεί να θέλετε να κάνετε το ένα ή το άλλο, και έτσι το pandas σας δίνει επιλογές και για τα δύο. Επειδή στην επιστήμη δεδομένων οι στήλες γενικά αντιπροσωπεύουν μεταβλητές και οι γραμμές αντιπροσωπεύουν παρατηρήσεις, είναι πιο πιθανό να αφαιρέσετε γραμμές δεδομένων. Η προεπιλεγμένη ρύθμιση για το `dropna()` είναι να αφαιρεί όλες τις γραμμές που περιέχουν οποιεσδήποτε κενές τιμές:\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": [
"Εάν είναι απαραίτητο, μπορείτε να αφαιρέσετε τις τιμές NA από τις στήλες. Χρησιμοποιήστε `axis=1` για να το κάνετε:\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": [
"Σημειώστε ότι αυτό μπορεί να αφαιρέσει πολλά δεδομένα που ίσως θέλετε να διατηρήσετε, ιδιαίτερα σε μικρότερα σύνολα δεδομένων. Τι γίνεται αν θέλετε απλώς να αφαιρέσετε γραμμές ή στήλες που περιέχουν αρκετές ή ακόμα και όλες τις τιμές null; Μπορείτε να ορίσετε αυτές τις ρυθμίσεις στο `dropna` με τις παραμέτρους `how` και `thresh`.\n",
"\n",
"Από προεπιλογή, `how='any'` (αν θέλετε να το ελέγξετε μόνοι σας ή να δείτε ποιες άλλες παραμέτρους έχει η μέθοδος, εκτελέστε `example4.dropna?` σε ένα κελί κώδικα). Εναλλακτικά, μπορείτε να ορίσετε `how='all'` ώστε να αφαιρέσετε μόνο γραμμές ή στήλες που περιέχουν όλες τις τιμές null. Ας επεκτείνουμε το παράδειγμα `DataFrame` για να δούμε αυτό στην πράξη στην επόμενη άσκηση.\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": [
"> Βασικά σημεία:\n",
"1. Η αφαίρεση κενών τιμών είναι καλή ιδέα μόνο αν το σύνολο δεδομένων είναι αρκετά μεγάλο.\n",
"2. Πλήρεις γραμμές ή στήλες μπορούν να αφαιρεθούν αν λείπουν τα περισσότερα δεδομένα τους.\n",
"3. Η μέθοδος `DataFrame.dropna(axis=)` βοηθά στην αφαίρεση κενών τιμών. Το όρισμα `axis` υποδεικνύει αν θα αφαιρεθούν γραμμές ή στήλες.\n",
"4. Μπορεί επίσης να χρησιμοποιηθεί το όρισμα `how`. Από προεπιλογή είναι ρυθμισμένο στο `any`. Έτσι, αφαιρεί μόνο εκείνες τις γραμμές/στήλες που περιέχουν οποιαδήποτε κενή τιμή. Μπορεί να ρυθμιστεί στο `all` για να καθορίσει ότι θα αφαιρέσουμε μόνο εκείνες τις γραμμές/στήλες όπου όλες οι τιμές είναι κενές.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "oXXSfQFHgRsF"
},
"source": [
"### Άσκηση:\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": [
"Η παράμετρος `thresh` σας δίνει πιο λεπτομερή έλεγχο: ορίζετε τον αριθμό των *μη μηδενικών* τιμών που μια γραμμή ή στήλη πρέπει να έχει για να διατηρηθεί:\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": [
"Εδώ, η πρώτη και η τελευταία σειρά έχουν αφαιρεθεί, επειδή περιέχουν μόνο δύο μη μηδενικές τιμές.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "mCcxLGyUgRsG"
},
"source": [
"### Συμπλήρωση κενών τιμών\n",
"\n",
"Μερικές φορές έχει νόημα να συμπληρώσουμε τις ελλείπουσες τιμές με τιμές που θα μπορούσαν να είναι έγκυρες. Υπάρχουν μερικές τεχνικές για τη συμπλήρωση κενών τιμών. Η πρώτη είναι η χρήση Γνώσης του Τομέα (γνώση του αντικειμένου στο οποίο βασίζεται το σύνολο δεδομένων) για να προσεγγίσουμε με κάποιο τρόπο τις ελλείπουσες τιμές.\n",
"\n",
"Μπορείτε να χρησιμοποιήσετε το `isnull` για να το κάνετε αυτό απευθείας, αλλά αυτό μπορεί να είναι κουραστικό, ειδικά αν έχετε πολλές τιμές να συμπληρώσετε. Επειδή αυτή είναι μια τόσο συνηθισμένη εργασία στην επιστήμη δεδομένων, το pandas παρέχει τη μέθοδο `fillna`, η οποία επιστρέφει ένα αντίγραφο του `Series` ή του `DataFrame` με τις ελλείπουσες τιμές αντικαταστημένες με μία της επιλογής σας. Ας δημιουργήσουμε ένα άλλο παράδειγμα `Series` για να δούμε πώς λειτουργεί αυτό στην πράξη.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "CE8S7louLezV"
},
"source": [
"### Κατηγορικά Δεδομένα (Μη αριθμητικά)\n",
"Ας εξετάσουμε πρώτα τα μη αριθμητικά δεδομένα. Στα σύνολα δεδομένων, υπάρχουν στήλες με κατηγορικά δεδομένα, π.χ. Φύλο, Αληθές ή Ψευδές κ.λπ.\n",
"\n",
"Στις περισσότερες από αυτές τις περιπτώσεις, αντικαθιστούμε τις ελλείπουσες τιμές με τη `mode` της στήλης. Για παράδειγμα, αν έχουμε 100 σημεία δεδομένων και 90 έχουν δηλώσει Αληθές, 8 έχουν δηλώσει Ψευδές και 2 δεν έχουν συμπληρώσει, τότε μπορούμε να συμπληρώσουμε τα 2 με Αληθές, λαμβάνοντας υπόψη ολόκληρη τη στήλη.\n",
"\n",
"Εδώ μπορούμε επίσης να χρησιμοποιήσουμε τη γνώση του πεδίου. Ας εξετάσουμε ένα παράδειγμα συμπλήρωσης με τη mode.\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": [
"Τώρα, ας βρούμε πρώτα τη διάμεσο πριν συμπληρώσουμε την τιμή `None` με τη διάμεσο.\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": [
"Λοιπόν, θα αντικαταστήσουμε το None με 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": [
"Όπως μπορούμε να δούμε, η τιμή null έχει αντικατασταθεί. Περιττό να πούμε ότι θα μπορούσαμε να είχαμε γράψει οτιδήποτε στη θέση του `'True'` και θα είχε αντικατασταθεί.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "heYe1I0dOmQ_"
},
"source": [
"### Αριθμητικά Δεδομένα\n",
"Τώρα, ας μιλήσουμε για τα αριθμητικά δεδομένα. Εδώ, έχουμε δύο κοινές μεθόδους για την αντικατάσταση των ελλειπόντων τιμών:\n",
"\n",
"1. Αντικατάσταση με τη Διάμεσο της γραμμής\n",
"2. Αντικατάσταση με τον Μέσο Όρο της γραμμής\n",
"\n",
"Αντικαθιστούμε με τη Διάμεσο σε περίπτωση δεδομένων με ασυμμετρία και ακραίες τιμές. Αυτό συμβαίνει επειδή η διάμεσος είναι ανθεκτική στις ακραίες τιμές.\n",
"\n",
"Όταν τα δεδομένα είναι κανονικοποιημένα, μπορούμε να χρησιμοποιήσουμε τον μέσο όρο, καθώς σε αυτή την περίπτωση, ο μέσος όρος και η διάμεσος θα είναι αρκετά κοντά.\n",
"\n",
"Αρχικά, ας πάρουμε μια στήλη που ακολουθεί κανονική κατανομή και ας συμπληρώσουμε την ελλείπουσα τιμή με τον μέσο όρο της στήλης.\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": [
"Ο μέσος όρος της στήλης είναι\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": [
"Συμπλήρωση με μέσο όρο\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": [
"Όπως μπορούμε να δούμε, η τιμή που έλειπε έχει αντικατασταθεί με τον μέσο όρο της.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "jIvF13a1i00Z"
},
"source": [
"Τώρα ας δοκιμάσουμε ένα άλλο dataframe, και αυτή τη φορά θα αντικαταστήσουμε τις τιμές None με τη διάμεσο της στήλης.\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": [
"Η διάμεσος της δεύτερης στήλης είναι\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": [
"Συμπλήρωση με διάμεσο\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": [
"Όπως μπορούμε να δούμε, η τιμή NaN έχει αντικατασταθεί από τη διάμεσο της στήλης\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": [
"Μπορείτε να συμπληρώσετε όλες τις κενές εγγραφές με μία μόνο τιμή, όπως `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": [
"> Βασικά σημεία:\n",
"1. Η συμπλήρωση των ελλειπόντων τιμών πρέπει να γίνεται είτε όταν υπάρχουν λίγα δεδομένα είτε όταν υπάρχει στρατηγική για τη συμπλήρωση των ελλειπόντων δεδομένων.\n",
"2. Η γνώση του πεδίου μπορεί να χρησιμοποιηθεί για τη συμπλήρωση ελλειπόντων τιμών μέσω προσέγγισης.\n",
"3. Για κατηγορικά δεδομένα, συνήθως οι ελλείπουσες τιμές αντικαθίστανται με τη συχνότερη τιμή της στήλης (mode).\n",
"4. Για αριθμητικά δεδομένα, οι ελλείπουσες τιμές συνήθως συμπληρώνονται με τον μέσο όρο (για κανονικοποιημένα σύνολα δεδομένων) ή τη διάμεσο της στήλης.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "FI9MmqFJgRsH"
},
"source": [
"### Άσκηση:\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": [
"Μπορείτε να **συμπληρώσετε προς τα εμπρός** τις κενές τιμές, δηλαδή να χρησιμοποιήσετε την τελευταία έγκυρη τιμή για να συμπληρώσετε μια κενή:\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": [
"Μπορείτε επίσης να **συμπληρώσετε προς τα πίσω** για να προωθήσετε την επόμενη έγκυρη τιμή προς τα πίσω ώστε να συμπληρώσετε μια κενή τιμή:\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": [
"Όπως ίσως μαντέψετε, αυτό λειτουργεί το ίδιο με τα DataFrames, αλλά μπορείτε επίσης να καθορίσετε έναν `άξονα` κατά μήκος του οποίου να συμπληρώσετε τις κενές τιμές:\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": [
"Παρατηρήστε ότι όταν δεν υπάρχει προηγούμενη τιμή για συμπλήρωση προς τα εμπρός, η τιμή null παραμένει.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "eeAoOU0RgRsJ"
},
"source": [
"### Άσκηση:\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": [
"Μπορείτε να είστε δημιουργικοί σχετικά με το πώς χρησιμοποιείτε το `fillna`. Για παράδειγμα, ας δούμε ξανά το `example4`, αλλά αυτή τη φορά ας συμπληρώσουμε τις ελλείπουσες τιμές με τον μέσο όρο όλων των τιμών στο `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": [
"Παρατηρήστε ότι η στήλη 3 εξακολουθεί να είναι χωρίς τιμές: η προεπιλεγμένη κατεύθυνση είναι να γεμίζονται οι τιμές κατά γραμμές.\n",
"\n",
"> **Συμπέρασμα:** Υπάρχουν πολλοί τρόποι για να αντιμετωπίσετε τις ελλείπουσες τιμές στα σύνολα δεδομένων σας. Η συγκεκριμένη στρατηγική που θα χρησιμοποιήσετε (αφαίρεση, αντικατάσταση ή ακόμα και ο τρόπος αντικατάστασης) θα πρέπει να καθορίζεται από τις ιδιαιτερότητες αυτών των δεδομένων. Θα αναπτύξετε καλύτερη αίσθηση για το πώς να χειρίζεστε τις ελλείπουσες τιμές όσο περισσότερο ασχολείστε και αλληλεπιδράτε με σύνολα δεδομένων.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "bauDnESIl9FH"
},
"source": [
"### Κωδικοποίηση Κατηγορικών Δεδομένων\n",
"\n",
"Τα μοντέλα μηχανικής μάθησης επεξεργάζονται μόνο αριθμούς και οποιαδήποτε μορφή αριθμητικών δεδομένων. Δεν μπορούν να καταλάβουν τη διαφορά μεταξύ ενός Ναι και ενός Όχι, αλλά μπορούν να διακρίνουν μεταξύ του 0 και του 1. Έτσι, αφού συμπληρώσουμε τις ελλείπουσες τιμές, πρέπει να κωδικοποιήσουμε τα κατηγορικά δεδομένα σε κάποια αριθμητική μορφή ώστε το μοντέλο να τα κατανοήσει.\n",
"\n",
"Η κωδικοποίηση μπορεί να γίνει με δύο τρόπους. Θα τους συζητήσουμε στη συνέχεια.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "uDq9SxB7mu5i"
},
"source": [
"**ΚΩΔΙΚΟΠΟΙΗΣΗ ΕΤΙΚΕΤΩΝ**\n",
"\n",
"Η κωδικοποίηση ετικετών είναι ουσιαστικά η μετατροπή κάθε κατηγορίας σε έναν αριθμό. Για παράδειγμα, ας πούμε ότι έχουμε ένα σύνολο δεδομένων με επιβάτες αεροπορικών εταιρειών και υπάρχει μια στήλη που περιέχει την κατηγορία τους ανάμεσα στις εξής ['business class', 'economy class', 'first class']. Εάν γίνει κωδικοποίηση ετικετών σε αυτό, θα μετατραπεί σε [0,1,2]. Ας δούμε ένα παράδειγμα μέσω κώδικα. Καθώς θα μάθουμε το `scikit-learn` στα επόμενα σημειωματάρια, δεν θα το χρησιμοποιήσουμε εδώ.\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": [
"Για να εκτελέσουμε κωδικοποίηση ετικετών στην 1η στήλη, πρέπει πρώτα να περιγράψουμε μια αντιστοίχιση από κάθε κατηγορία σε έναν αριθμό, πριν την αντικατάσταση\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": [
"Όπως μπορούμε να δούμε, το αποτέλεσμα ταιριάζει με αυτό που περιμέναμε να συμβεί. Λοιπόν, πότε χρησιμοποιούμε την κωδικοποίηση ετικετών; Η κωδικοποίηση ετικετών χρησιμοποιείται σε μία ή και στις δύο από τις ακόλουθες περιπτώσεις:\n",
"1. Όταν ο αριθμός των κατηγοριών είναι μεγάλος\n",
"2. Όταν οι κατηγορίες έχουν σειρά.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "eQPAPVwsqWT7"
},
"source": [
"**ΚΩΔΙΚΟΠΟΙΗΣΗ ONE HOT**\n",
"\n",
"Ένας άλλος τύπος κωδικοποίησης είναι η Κωδικοποίηση One Hot. Σε αυτόν τον τύπο κωδικοποίησης, κάθε κατηγορία της στήλης προστίθεται ως ξεχωριστή στήλη και κάθε δεδομένο λαμβάνει τιμή 0 ή 1 ανάλογα με το αν περιέχει αυτήν την κατηγορία. Έτσι, αν υπάρχουν n διαφορετικές κατηγορίες, n στήλες θα προστεθούν στο dataframe.\n",
"\n",
"Για παράδειγμα, ας πάρουμε το ίδιο παράδειγμα με τις κατηγορίες αεροπλάνου. Οι κατηγορίες ήταν: ['business class', 'economy class', 'first class']. Επομένως, αν εφαρμόσουμε την κωδικοποίηση one hot, οι εξής τρεις στήλες θα προστεθούν στο 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": [
"Ας εκτελέσουμε one hot encoding στην πρώτη στήλη\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": [
"Κάθε στήλη με one hot encoding περιέχει 0 ή 1, που καθορίζει αν αυτή η κατηγορία υπάρχει για αυτό το δεδομένο.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "bDnC4NQOu0qr"
},
"source": [
"Πότε χρησιμοποιούμε το one hot encoding; Το one hot encoding χρησιμοποιείται σε μία ή και στις δύο από τις παρακάτω περιπτώσεις:\n",
"\n",
"1. Όταν ο αριθμός των κατηγοριών και το μέγεθος του συνόλου δεδομένων είναι μικρότερο.\n",
"2. Όταν οι κατηγορίες δεν ακολουθούν κάποια συγκεκριμένη σειρά.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XnUmci_4uvyu"
},
"source": [
"> Βασικά Σημεία:\n",
"1. Η κωδικοποίηση γίνεται για τη μετατροπή μη αριθμητικών δεδομένων σε αριθμητικά δεδομένα.\n",
"2. Υπάρχουν δύο τύποι κωδικοποίησης: Κωδικοποίηση Ετικετών και Κωδικοποίηση One Hot, οι οποίες μπορούν να πραγματοποιηθούν ανάλογα με τις απαιτήσεις του συνόλου δεδομένων.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "K8UXOJYRgRsJ"
},
"source": [
"## Αφαίρεση διπλών δεδομένων\n",
"\n",
"> **Στόχος μάθησης:** Μέχρι το τέλος αυτής της υποενότητας, θα πρέπει να είστε εξοικειωμένοι με την αναγνώριση και την αφαίρεση διπλών τιμών από DataFrames.\n",
"\n",
"Εκτός από τα ελλιπή δεδομένα, συχνά θα συναντήσετε διπλά δεδομένα σε σύνολα δεδομένων πραγματικού κόσμου. Ευτυχώς, το pandas παρέχει έναν εύκολο τρόπο για την ανίχνευση και την αφαίρεση διπλών εγγραφών.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "qrEG-Wa0gRsJ"
},
"source": [
"### Εντοπισμός διπλότυπων: `duplicated`\n",
"\n",
"Μπορείτε εύκολα να εντοπίσετε διπλότυπες τιμές χρησιμοποιώντας τη μέθοδο `duplicated` στο pandas, η οποία επιστρέφει μια μάσκα Boolean που δείχνει αν μια εγγραφή σε ένα `DataFrame` είναι διπλότυπη με κάποια προηγούμενη. Ας δημιουργήσουμε ένα άλλο παράδειγμα `DataFrame` για να το δούμε αυτό στην πράξη.\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": [
"### Αφαίρεση διπλότυπων: `drop_duplicates`\n",
"Το `drop_duplicates` επιστρέφει απλώς ένα αντίγραφο των δεδομένων για τα οποία όλες οι τιμές `duplicated` είναι `False`:\n"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 142
},
"id": "w_YPpqIqgRsK",
"outputId": "ac66bd2f-8671-4744-87f5-8b8d96553dea",
"trusted": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>letters</th>\n",
" <th>numbers</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>A</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>B</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>B</td>\n",
" <td>3</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" letters numbers\n",
"0 A 1\n",
"1 B 2\n",
"3 B 3"
]
},
"execution_count": 54,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"example6.drop_duplicates()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "69AqoCZAgRsK"
},
"source": [
"Τόσο οι `duplicated` όσο και οι `drop_duplicates` από προεπιλογή λαμβάνουν υπόψη όλες τις στήλες, αλλά μπορείτε να καθορίσετε ότι εξετάζουν μόνο ένα υποσύνολο στηλών στο `DataFrame` σας:\n"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 111
},
"id": "BILjDs67gRsK",
"outputId": "ef6dcc08-db8b-4352-c44e-5aa9e2bec0d3",
"trusted": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>letters</th>\n",
" <th>numbers</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>A</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>B</td>\n",
" <td>2</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" letters numbers\n",
"0 A 1\n",
"1 B 2"
]
},
"execution_count": 55,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"example6.drop_duplicates(['letters'])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "GvX4og1EgRsL"
},
"source": [
"> **Συμπέρασμα:** Η αφαίρεση διπλότυπων δεδομένων είναι ένα απαραίτητο μέρος σχεδόν κάθε έργου επιστήμης δεδομένων. Τα διπλότυπα δεδομένα μπορούν να αλλάξουν τα αποτελέσματα των αναλύσεών σας και να σας δώσουν ανακριβή αποτελέσματα!\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Έλεγχοι Ποιότητας Δεδομένων στον Πραγματικό Κόσμο\n",
"\n",
"> **Στόχος μάθησης:** Μέχρι το τέλος αυτής της ενότητας, θα πρέπει να είστε εξοικειωμένοι με την ανίχνευση και διόρθωση κοινών προβλημάτων ποιότητας δεδομένων στον πραγματικό κόσμο, όπως ασυνεπείς κατηγοριακές τιμές, μη φυσιολογικές αριθμητικές τιμές (ακραίες τιμές) και διπλότυπες οντότητες με παραλλαγές.\n",
"\n",
"Ενώ οι ελλείπουσες τιμές και τα ακριβή διπλότυπα είναι συνηθισμένα προβλήματα, τα σύνολα δεδομένων στον πραγματικό κόσμο συχνά περιέχουν πιο λεπτές δυσκολίες:\n",
"\n",
"1. **Ασυνεπείς κατηγοριακές τιμές**: Η ίδια κατηγορία γραμμένη διαφορετικά (π.χ., \"USA\", \"U.S.A\", \"United States\")\n",
"2. **Μη φυσιολογικές αριθμητικές τιμές**: Ακραίες τιμές που υποδεικνύουν σφάλματα καταχώρησης δεδομένων (π.χ., ηλικία = 999)\n",
"3. **Σχεδόν διπλότυπες γραμμές**: Εγγραφές που αντιπροσωπεύουν την ίδια οντότητα με μικρές παραλλαγές\n",
"\n",
"Ας εξερευνήσουμε τεχνικές για την ανίχνευση και αντιμετώπιση αυτών των προβλημάτων.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Δημιουργία ενός Δείγματος \"Μη Καθαρού\" Συνόλου Δεδομένων\n",
"\n",
"Αρχικά, ας δημιουργήσουμε ένα δείγμα συνόλου δεδομένων που περιέχει τους τύπους προβλημάτων που συναντάμε συχνά σε δεδομένα πραγματικού κόσμου:\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. Εντοπισμός Ασυνεπών Τιμών Κατηγορίας\n",
"\n",
"Παρατηρήστε ότι η στήλη `country` έχει πολλαπλές αναπαραστάσεις για τις ίδιες χώρες. Ας εντοπίσουμε αυτές τις ασυνέπειες:\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": [
"#### Τυποποίηση Κατηγορικών Τιμών\n",
"\n",
"Μπορούμε να δημιουργήσουμε έναν χάρτη για να τυποποιήσουμε αυτές τις τιμές. Μια απλή προσέγγιση είναι να μετατρέψουμε σε πεζά και να δημιουργήσουμε ένα λεξικό αντιστοίχισης:\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": [
"**Εναλλακτική: Χρήση Ασαφούς Αντιστοίχισης**\n",
"\n",
"Για πιο σύνθετες περιπτώσεις, μπορούμε να χρησιμοποιήσουμε την ασαφή αντιστοίχιση συμβολοσειρών με τη βιβλιοθήκη `rapidfuzz` για να εντοπίσουμε αυτόματα παρόμοιες συμβολοσειρές:\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. Εντοπισμός Αφύσικων Αριθμητικών Τιμών (Ακραίες Τιμές)\n",
"\n",
"Κοιτάζοντας τη στήλη `age`, παρατηρούμε κάποιες ύποπτες τιμές όπως 199 και -5. Ας χρησιμοποιήσουμε στατιστικές μεθόδους για να εντοπίσουμε αυτές τις ακραίες τιμές.\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": [
"#### Χρήση της Μεθόδου IQR (Ενδοτεταρτημοριακό Εύρος)\n",
"\n",
"Η μέθοδος IQR είναι μια αξιόπιστη στατιστική τεχνική για την ανίχνευση ακραίων τιμών, η οποία είναι λιγότερο ευαίσθητη σε ακραίες τιμές:\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": [
"#### Χρήση της Μεθόδου Z-Score\n",
"\n",
"Η μέθοδος Z-score εντοπίζει τις ακραίες τιμές με βάση τις τυπικές αποκλίσεις από τον μέσο όρο:\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": [
"#### Διαχείριση Ακραίων Τιμών\n",
"\n",
"Μόλις εντοπιστούν, οι ακραίες τιμές μπορούν να διαχειριστούν με διάφορους τρόπους:\n",
"1. **Αφαίρεση**: Διαγραφή γραμμών με ακραίες τιμές (αν πρόκειται για σφάλματα)\n",
"2. **Περιορισμός**: Αντικατάσταση με οριακές τιμές\n",
"3. **Αντικατάσταση με NaN**: Θεώρηση ως ελλιπή δεδομένα και χρήση τεχνικών συμπλήρωσης\n",
"4. **Διατήρηση**: Αν είναι νόμιμες ακραίες τιμές\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. Εντοπισμός Σχεδόν Διπλότυπων Γραμμών\n",
"\n",
"Παρατηρήστε ότι το σύνολο δεδομένων μας έχει πολλαπλές εγγραφές για τον \"John Smith\" με ελαφρώς διαφορετικές τιμές. Ας εντοπίσουμε πιθανά διπλότυπα με βάση την ομοιότητα των ονομάτων.\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": [
"#### Εύρεση Σχεδόν Διπλότυπων με Ασαφή Αντιστοίχιση\n",
"\n",
"Για πιο εξελιγμένη ανίχνευση διπλότυπων, μπορούμε να χρησιμοποιήσουμε την ασαφή αντιστοίχιση για να βρούμε παρόμοια ονόματα:\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": [
"#### Διαχείριση Διπλότυπων\n",
"\n",
"Αφού εντοπιστούν, πρέπει να αποφασίσετε πώς να διαχειριστείτε τα διπλότυπα:\n",
"1. **Διατήρηση της πρώτης εμφάνισης**: Χρησιμοποιήστε `drop_duplicates(keep='first')`\n",
"2. **Διατήρηση της τελευταίας εμφάνισης**: Χρησιμοποιήστε `drop_duplicates(keep='last')`\n",
"3. **Συγκέντρωση πληροφοριών**: Συνδυάστε πληροφορίες από διπλότυπες γραμμές\n",
"4. **Χειροκίνητη ανασκόπηση**: Σημειώστε για ανθρώπινη ανασκόπηση\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": [
"### Περίληψη: Ολοκληρωμένη Διαδικασία Καθαρισμού Δεδομένων\n",
"\n",
"Ας τα συνδυάσουμε όλα σε μια ολοκληρωμένη διαδικασία καθαρισμού:\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": [
"### 🎯 Άσκηση Πρόκλησης\n",
"\n",
"Τώρα είναι η σειρά σου! Παρακάτω υπάρχει μια νέα γραμμή δεδομένων με πολλαπλά προβλήματα ποιότητας. Μπορείς:\n",
"\n",
"1. Να εντοπίσεις όλα τα προβλήματα σε αυτή τη γραμμή\n",
"2. Να γράψεις κώδικα για να διορθώσεις κάθε πρόβλημα\n",
"3. Να προσθέσεις τη διορθωμένη γραμμή στο σύνολο δεδομένων\n",
"\n",
"Εδώ είναι τα προβληματικά δεδομένα:\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": [
"### Βασικά Σημεία\n",
"\n",
"1. **Ασυνεπείς κατηγορίες** είναι συχνές σε δεδομένα του πραγματικού κόσμου. Ελέγξτε πάντα τις μοναδικές τιμές και τυποποιήστε τις χρησιμοποιώντας αντιστοιχίσεις ή μεθόδους ασαφούς αντιστοίχισης.\n",
"\n",
"2. **Ακραίες τιμές** μπορούν να επηρεάσουν σημαντικά την ανάλυσή σας. Χρησιμοποιήστε γνώση του πεδίου σε συνδυασμό με στατιστικές μεθόδους (IQR, Z-score) για να τις εντοπίσετε.\n",
"\n",
"3. **Σχεδόν διπλότυπα** είναι πιο δύσκολο να εντοπιστούν από τα ακριβή διπλότυπα. Σκεφτείτε να χρησιμοποιήσετε ασαφή αντιστοίχιση και να κανονικοποιήσετε τα δεδομένα (μετατροπή σε πεζά, αφαίρεση κενών) για να τα αναγνωρίσετε.\n",
"\n",
"4. **Ο καθαρισμός δεδομένων είναι επαναληπτικός**. Ίσως χρειαστεί να εφαρμόσετε πολλαπλές τεχνικές και να αναθεωρήσετε τα αποτελέσματα πριν ολοκληρώσετε το καθαρισμένο σύνολο δεδομένων.\n",
"\n",
"5. **Καταγράψτε τις αποφάσεις σας**. Κρατήστε σημειώσεις για τα βήματα καθαρισμού που εφαρμόσατε και τους λόγους, καθώς αυτό είναι σημαντικό για την αναπαραγωγιμότητα και τη διαφάνεια.\n",
"\n",
"> **Καλύτερη Πρακτική:** Πάντα να κρατάτε ένα αντίγραφο των αρχικών \"ακαθάριστων\" δεδομένων σας. Μην αντικαθιστάτε ποτέ τα αρχεία πηγής σας - δημιουργήστε καθαρισμένες εκδόσεις με σαφείς ονομασίες, όπως `data_cleaned.csv`.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Αποποίηση ευθύνης**: \nΑυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.\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:10:10+00:00",
"source_file": "2-Working-With-Data/08-data-preparation/notebook.ipynb",
"language_code": "el"
}
},
"nbformat": 4,
"nbformat_minor": 0
}