{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "name": "5_Python_packages.ipynb", "provenance": [], "collapsed_sections": [], "toc_visible": true, "include_colab_link": true }, "kernelspec": { "name": "python3", "display_name": "Python 3" } }, "cells": [ { "cell_type": "markdown", "metadata": { "id": "view-in-github", "colab_type": "text" }, "source": [ "\"Open" ] }, { "cell_type": "markdown", "metadata": { "id": "DfQ-d2onvooo", "colab_type": "text" }, "source": [ "Mickaël Tits\n", "CETIC\n", "mickael.tits@cetic.be" ] }, { "cell_type": "markdown", "metadata": { "id": "Ug1Bj8_tAVWq", "colab_type": "text" }, "source": [ "# Chapitre 5 - Les librairies Python pour l'analyse de données\n", "\n", "Une des grandes forces du langage de programmation Python est l'énorme communauté de développeurs qui développent et maintiennent un grand nombre de librairies, facilitant la vie desprogrammeurs. Ces librairies permettent d'utiliser des nouveaux types d'objets spécialisés, aux applications très variées, dont par exemple l'import/export/le traitement/la visualisation de données spécifiques, de l'analyse mathématique/statistique/scientifique poussée, l'interfaçage et la connecticité avec d'autres outils informatiques, etc.\n", "\n", "Dans le domaine de l'analyse de données en particulier, voici une liste de librairies incontourables que nous allons voir dans le cadre de ce cours:\n", "* [numpy](https://numpy.org/) : librairie de calcul scientifique (algèbre, calcul matriciel, stochastique, etc.)\n", "* [scipy](https://www.scipy.org/): librairie de calcul scientifique et statistique (reposant sur numpy)\n", "* [pandas](https://pandas.pydata.org/) : librairie permettant la représentation, la manipulation et l'analyse de données sous forme de tableaux (ou DataFrames)\n", "* [matplotlib](https://matplotlib.org/) : librairie de visualisation graphique de données (voir Chapitre 6)\n", "\n", "\n", "Pour importer un package, il faut tout d'abord qu'il soit installé sur la machine (ce qui est déjà fait la plupart du temps dans Google Colab).\n", "Ensuite, il faut utiliser les mots-clés suivants:\n", "\n", "**`import`** `package` **`as`** `alias`\n", "\n", "ou:\n", "\n", "**`from`** `package` **`import`** `subpackage` **`as`** `alias`\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "gBY_raFzHDU5", "colab_type": "text" }, "source": [ "# `Numpy`\n", "Numpy est une librairie de calcul mathématique. Elle inclut notamment l'objet **`ndarray`** (n-dimensional array) qui est une représentation d'un tableau multidimensionnel (un tenseur). On peut notamment utiliser cet objet pour représenter une matrice ou un vecteur. Le package dispose de nombreuses fonctions et méthodes permettant notamment des opérations algébriques sur ces objets, ou la génération de nombres aléatoires." ] }, { "cell_type": "code", "metadata": { "id": "r52k4kgIBUNU", "colab_type": "code", "colab": {} }, "source": [ "import numpy as np\n", "\n", "price_list = [ 100000, 300000, 250000]\n", "\n", "price_array = np.array(price_list)\n", "\n", "print(price_array)\n", "\n", "print(\"shape:\", price_array.shape)\n", "print(\"mean:\", price_array.mean())\n", "print(\"argmax:\", price_array.argmax())\n", "print(\"cumsum:\", price_array.cumsum())\n" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "R5iFYHDdFnsK", "colab_type": "code", "colab": {} }, "source": [ "my_array1 = np.array([[1,2,3]])\n", "my_array2 = np.array([[4,5,6]])\n", "\n", "print(my_array1.shape)\n", "\n", "#element-wise\n", "print(my_array1*my_array2)\n", "#matrix product\n", "print(my_array1@my_array2.T)" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "4xn6xR2tCu_4", "colab_type": "code", "colab": {} }, "source": [ "print(\"Opérations de base sur des listes => concaténation:\", (price_list + price_list)*2)" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "NOO8Aqh3DTdD", "colab_type": "code", "colab": {} }, "source": [ "print(\"Opérations de base sur un array => algèbre:\", (price_array + price_array)*2/100%42)" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "5UFH469xK06U", "colab_type": "text" }, "source": [ "# `Scipy`\n", "\n", "Scipy est une librairie de calcul scientifique, et plus particulièrement de statistiques.\n", "Elle se base sur Numpy pour la représentation des données mathématiques." ] }, { "cell_type": "code", "metadata": { "id": "NKPGpZsAK3F3", "colab_type": "code", "colab": {} }, "source": [ "from scipy import stats\n", "\n", "#le package random permet de générer des nombres (pseudo-)aléatoires\n", "from numpy import random as rnd\n", "\n", "#génération d'un array contenant 100 valeurs aléatoires suivant une distribution gaussienne (randn = normal distribution; rand = uniform distribution)\n", "my_array = rnd.randn(100)\n", "\n", "#description statistique\n", "stats.describe(my_array)" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "Z-9f3Rj55k6C", "colab_type": "code", "colab": {} }, "source": [ "#Distribution normale standard:\n", "print(stats.norm.pdf(0), stats.norm.cdf(0))\n", "stats.norm.cdf(1)-stats.norm.cdf(0)" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "LTs6tGklut_5", "colab_type": "text" }, "source": [ "Exemple: simulons une séquence de 100 jets de dés, et analysons les statistiques:" ] }, { "cell_type": "code", "metadata": { "id": "9g4YP0LjtM3h", "colab_type": "code", "colab": {} }, "source": [ "#Jet de dé: distribution uniforme et discrète des nombres [1,2,3,4,5,6]\n", "#tosses = np.ceil(rnd.rand(100)*6).astype(int)\n", "#plus rapide:\n", "tosses = np.random.randint(1,7,100)\n", "#print(tosses)\n", "print(stats.describe(tosses))\n" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "XxRAWOR07RvF", "colab_type": "text" }, "source": [ "Exemple de test statistique: Student's t-test" ] }, { "cell_type": "code", "metadata": { "id": "iLR3cmCy64T1", "colab_type": "code", "colab": {} }, "source": [ "stats.ttest_ind(rnd.randn(100), rnd.randn(100)+1)" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "4aHeHmpc7tXp", "colab_type": "code", "colab": {} }, "source": [ "stats.f_oneway(rnd.randn(100), rnd.randn(100)+1)" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "0edS6WEcIC0v", "colab_type": "text" }, "source": [ "# `Pandas`\n", "\n", "Pandas est une librairie permettant la représentation, la manipulation et l'analyse de données sous forme de tableaux. \n", "\n", "La librairie dispose de deux objets centraux: \n", "* La **`Series`**: une série de données à une dimension\n", "* Le **`Dataframe`**: un tableau de données à deux dimensions. (remarque: l'extraction d'une ligne ou d'une colonne d'un **`DataFrame`** donne une **`Series`**).\n", "\n", "Ces deux objets disposent d'un grand nombre de fonctions et méthodes qui peuvent être utilisées pour accéder/manipuler/extraire/modifier/filtrer/ajouter/supprimer des données, et extraire des statistiques (aussi appelés **aggrégats**).\n", "\n", "La liste complète des méthodes peut se trouver ici: [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/frame.html), [Series](https://pandas.pydata.org/pandas-docs/stable/reference/series.html)" ] }, { "cell_type": "markdown", "metadata": { "id": "OONEpcjUVceC", "colab_type": "text" }, "source": [ "## Reprenons l'inventaire des biens immobiliers" ] }, { "cell_type": "code", "metadata": { "id": "tT6OCfRxVYna", "colab_type": "code", "colab": {} }, "source": [ "#Un inventaire de biens immobiliers\n", "\n", "houses_dataset = {\"address\":[\"Rue de Fer 26, 5000 Namur\",\n", " \"Rue de Bruxelles 42, 5000 Namur\",\n", " \"Porte de Namur 25, Bruxelles\",\n", " \"Rue de L'Eglise 42, Charleroi\",\n", " \"Rue Saint-ghislain 30, 6224 Fleurus\",\n", " \"Rue de la Closière 20, Fleurus\",\n", " \"Rue de la Closière 20, Fleurus\",\n", " \"Rue de Fer 25, 5000 Namur\",\n", " \"Rue du Luxembourg 15, 1000 Bruxelles\",\n", " \"NaN\",\n", " \"Rue de Bruxelles 42, 5000 Namur\",\n", " \"Rue de la Loi 50, Bruxelles\"],\n", " \"website\":[\"immoweb\",\"immoweb\",\"immoweb\",\"immoweb\",\"immoweb\",\"immoweb\",\"immoweb\",\"immovlan\",\"immovlan\",\"immovlan\",\"immovlan\",\"immovlan\"],\n", " \"price\": [400000,\n", " 350000,\n", " 400000,\n", " 150000,\n", " \"330000\",\n", " 230000,\n", " 230000,\n", " 0,\n", " -100,\n", " \"cent mille\",\n", " 350000,\n", " 700000],\n", " \"surface\":[150,\n", " 200,\n", " 120,\n", " 150,\n", " 320,\n", " 175,\n", " 170,\n", " 170,\n", " 100,\n", " 100,\n", " 200,\n", " 220],\n", " \"rooms\":[4,5,3,5,5,2,3,3,\"two\",0,4,3]}\n", "\n", "print(houses_dataset)" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "wALiLgvxVZjY", "colab_type": "text" }, "source": [ "## Préparation du dataframe" ] }, { "cell_type": "code", "metadata": { "id": "U-3impyQwfAd", "colab_type": "code", "colab": {} }, "source": [ "import pandas as pd\n", "\n", "df = pd.DataFrame(houses_dataset)\n", "#print(df) #moins joli\n", "display(df) #plus joli" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "LHWOxgLqMjyP", "colab_type": "code", "colab": {} }, "source": [ "#convertir certaines colonnes en valeurs numériques (les valeurs invalides deviennent des NaN - not a number)\n", "str_cols = df.columns[:2] #address, website\n", "num_cols = df.columns[2:]# price, surface, rooms\n", "\n", "for col in num_cols:\n", " df[col] = pd.to_numeric(df[col], errors = \"coerce\") #errors = \"coerce\" transforme en NaN les données qui ne peuvent être converties en nombre\n", "\n", "df0 = df\n", "\n", "df" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "G5Xped0qDBTf", "colab_type": "text" }, "source": [ "## Concaténation de DataFrames" ] }, { "cell_type": "code", "metadata": { "id": "3mktMs2bDEkQ", "colab_type": "code", "colab": {} }, "source": [ "newhouses = pd.DataFrame({ \"address\": [\"Rue de la Loi 51, Bruxelles\", \"Rue de la Loi 52, Bruxelles\", \"Rue de la Loi 53, Bruxelles\", \"Rue de Fer 27, Namur\", \"Rue de Fer 28, Namur\", \"Rue de Fer 29, Namur\"], \n", " \"website\" : [\"immoweb\",\"immovlan\",\"immovlan\",\"immoweb\",\"immoweb\",\"immovlan\"], \n", " \"surface\" : [120, 150, 170, 140, 160, 180], \n", " \"price\" : [280000, 400000, 480000, 280000, 320000, 350000], \n", " \"rooms\" : [3,4,5,3,4,5]})\n", "\n", "df = pd.concat([df0, newhouses], ignore_index = True)\n", "\n", "df1 = df#on le garde pour plus tard\n", "\n", "df" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "Q-iFzWpqXcuv", "colab_type": "text" }, "source": [ "## Accès aux données d'un dataframe" ] }, { "cell_type": "code", "metadata": { "id": "fYUO8hwPXoRn", "colab_type": "code", "colab": {} }, "source": [ "#Les labels du dataframe (i.e. les titres des lignes et des colonnes)\n", "print(df.index) # labels des lignes\n", "print(df.index.to_list()) # labels des lignes" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "mwMmuPwRar4z", "colab_type": "code", "colab": {} }, "source": [ "print(df.columns) #labels des colonnes\n", "print(df.columns.to_list()) #labels des colonnes" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "5EhDyw72azIW", "colab_type": "code", "colab": {} }, "source": [ "df.transpose() #permet de transposer le tableau" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "5o6yoFzTYnZX", "colab_type": "code", "colab": {} }, "source": [ "df.set_index(\"address\") #permet de modifier l'index" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "OWuB83OZYELm", "colab_type": "code", "colab": {} }, "source": [ "#Accès à une colonne\n", "print(df[\"price\"])\n", "#ou\n", "df.price" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "qzrlDEKiYxU3", "colab_type": "code", "colab": {} }, "source": [ "#Accès à plusieurs colonnes\n", "df[[\"price\",\"surface\"]]" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "H8tESOPCYpFN", "colab_type": "code", "colab": {} }, "source": [ "#Accès à une ligne\n", "#par label: loc\n", "print(df.loc[0])" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "kBGAsJHja9Iu", "colab_type": "code", "colab": {} }, "source": [ "#par un entier: iloc (dans ce cas ça revient au même puisque l'index correspond à des entiers de 0 à 11)\n", "df.iloc[0]" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "jzz6e0ibZATG", "colab_type": "code", "colab": {} }, "source": [ "#Accès à une ligne\n", "print(df.set_index(\"address\").loc[\"NaN\"])" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "ZaERu77dabJp", "colab_type": "code", "colab": {} }, "source": [ "df.set_index(\"address\").iloc[0]" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "7XQBSbOKZRkg", "colab_type": "code", "colab": {} }, "source": [ "#Accès à un/plusieurs élément(s)\n", "df.iloc[0,0]" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "qXzeZQxQaHNg", "colab_type": "code", "colab": {} }, "source": [ "df.iloc[0:2,0:2]" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "1xTeVue7aJon", "colab_type": "code", "colab": {} }, "source": [ "df.loc[0,\"price\"]" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "msEMFzalaOMI", "colab_type": "code", "colab": {} }, "source": [ "df.loc[0,[\"price\",\"surface\"]]" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "iqErTTDoaPj6", "colab_type": "code", "colab": {} }, "source": [ "df.loc[0:3,[\"price\",\"surface\"]]" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "pBs1LmXgcgk5", "colab_type": "text" }, "source": [ "## Exploration statistique du dataframe\n" ] }, { "cell_type": "markdown", "metadata": { "id": "czsPJk69ihKw", "colab_type": "text" }, "source": [ "Avant même de corriger le dataframe, il peut être intéressant de réaliser une première exploration statistique, qui permet parfois de se rendre compte directement des données à corriger.\n", "\n", "df.describe() permet de calculer différents aggrégats (des statistiques de base) pour toutes les colonnes numériques." ] }, { "cell_type": "code", "metadata": { "id": "ipSGQZLvcOIX", "colab_type": "code", "colab": {} }, "source": [ "df.describe()" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "bd8RQ1OpEI8q", "colab_type": "text" }, "source": [ "* On remarque directement des données incohérentes: le prix minimum est négatif, et le nombre de pièces minimum est 0. Il faut donc au moins corriger ces deux caractéristiques.\n", "* Il manque des valeurs pour les colonnes price et rooms (17 au lieu de 18). (Note: df.dropna() permet d'éliminer ces lignes invalides)\n", "* Les valeurs moyennes et maximales semble cohérentes." ] }, { "cell_type": "markdown", "metadata": { "id": "gygRr631emVQ", "colab_type": "text" }, "source": [ "La méthode \"groupby\" permet de grouper les données selon leur adresse (on obtient un groupe par addresse unique), et la méthode \"count\" permet ensuite de compter les valeurs pour chaque groupe. Ceci permet de directement identifier les doublons, et les données non-valides.\n" ] }, { "cell_type": "code", "metadata": { "id": "E6h4M8_4dHJ5", "colab_type": "code", "colab": {} }, "source": [ "df.groupby(\"address\").count()" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "Gi120EbAEMYS", "colab_type": "text" }, "source": [ "\n", "* On distingue 2 doublons: Rue de Bruxelles 42, 5000 Namur et Rue de la Closière 20, Fleurus\n", "\n", "* On remarque aussi des données invalides pour deux adresses: il manque le prix pour \"NaN\", de le nombre de pièces pour \"Rue du Luxembourg 15, 1000 Bruxelles\"\n", "* On aperçoit une adresse invalide: \"NaN\", qu'on peut enlever manuellement\n", "\n", "Note: df.dropna() permet d'éliminer directement ces données invalides (des NaN)" ] }, { "cell_type": "markdown", "metadata": { "id": "Ri8VqV6lhD7t", "colab_type": "text" }, "source": [ "On peut réaliser le même processus pour l'autre colonne textuelle: website\n", "\n", "* On remarque en l'occurrence que plus de données viennent d'immoweb, et plus particulièrement que les données invalides viennent toutes de immovlan" ] }, { "cell_type": "code", "metadata": { "id": "Asdqxln6g7Mj", "colab_type": "code", "colab": {} }, "source": [ "df.groupby(\"website\").count()" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "grHijEqKVR2e", "colab_type": "text" }, "source": [ "## Correction du dataframe en une seule instruction\n", "* Retire les données invalides:\n", " * string à \"NaN\",\"\" ou \" \"\n", " * nombre négatif\n", " * nombre défini à NaN\n", "* Retire les doublons" ] }, { "cell_type": "code", "metadata": { "id": "RSYtHkwfUSIr", "colab_type": "code", "colab": {} }, "source": [ "#Correction du dataframe en une seule instruction: retire toutes les données invalides et les doublons\n", "df = df[~df.address.isin([\"NaN\",\"\",\" \"]) & \\\n", " (df.price > 0) & (df.rooms > 0)]\\\n", " .dropna()\\\n", " .drop_duplicates(\"address\")\n", "\n", "df\n" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "4JgQN1tuVOuo", "colab_type": "text" }, "source": [ "## Correction étape par étape" ] }, { "cell_type": "code", "metadata": { "id": "t6hD3BYPbd4o", "colab_type": "code", "colab": {} }, "source": [ "#On reprend le dataframe non-corrigé pour comparer\n", "df = df1\n", "df" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "xBZMkmqlOva3", "colab_type": "code", "colab": {} }, "source": [ "#Pour les colonnes de texte, retirer les valeurs invalides (NaN ou \"\" ou \" \")\n", "\n", "#df = df[df.address != \"NaN\"]\n", "#Ou pus complet\n", "df = df[~df.address.isin([\"NaN\",\"\",\" \"])]\n", "df" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "b9hJbbkVQkpI", "colab_type": "code", "colab": {} }, "source": [ "#Elimine les lignes contenant des NaN\n", "df = df.dropna()\n", "df" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "29AAOyEPQ034", "colab_type": "code", "colab": {} }, "source": [ "#Retirer les valeurs numériques incohérentes\n", "df = df[(df.price > 0) & (df.rooms > 0)]\n", "df" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "Op6hoKP4kxgg", "colab_type": "code", "colab": {} }, "source": [ "#On stocke la version avec doublons pour plus tard\n", "dfdup = df" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "Fw5esCh7R5dO", "colab_type": "code", "colab": {} }, "source": [ "#Retirer les doublons\n", "\n", "#df =df.drop_duplicates(\"address\")\n", "#Par défaut, le premier élément est gardé. On peut aussi garder le dernier (ce qui gardera notamment plus d'éléments d'immovlan)\n", "df = dfdup.drop_duplicates(\"address\", keep = \"last\")\n", "df" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "YbhbjCpPLkyP", "colab_type": "code", "colab": {} }, "source": [ "#filtrer les données d'immoweb\n", "df[df.website == \"immoweb\"]" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "4mRu-QHMcJZ9", "colab_type": "text" }, "source": [ "## Aggrégats" ] }, { "cell_type": "code", "metadata": { "id": "UrEN2kqJcKq1", "colab_type": "code", "colab": {} }, "source": [ "df.mean()" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "lXghl-S6i5yQ", "colab_type": "code", "colab": {} }, "source": [ "df[df.website == \"immoweb\"].mean()\n", "#On remarque que les maisons d'immoweb sont en moyenne moins chère que la moyenne totale" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "343kdifbcMlm", "colab_type": "code", "colab": {} }, "source": [ "df.count()" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "my_jdhJGb85j", "colab_type": "text" }, "source": [ "## Comparer deux groupes (aggrégats groupés)\n", "Avec Pandas, il est très facile de comparer différents groupes d'échantillons, grâce à la méthode `pandas.DataFrame.groupby`, qui permet de faire des aggrégats groupés.\n", "\n", "Remarque: la méthode `pandas.DataFrame.groupby` renvoie en fait un objet d'un nouveau type (`GroupBy`), qui permet de gérer des groupements de données, et dispose de ses propres méthodes dont la liste complète peut se trouver ici: https://pandas.pydata.org/pandas-docs/stable/reference/groupby.html" ] }, { "cell_type": "code", "metadata": { "id": "lhGeXuXtMnye", "colab_type": "code", "colab": {} }, "source": [ "#Comparer les deux plateformes: c'est direct avec la méthode \"groupby\"\n", "display(df.groupby(\"website\").count())\n", "display(df.groupby(\"website\").mean())" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "OTPrsUHjjLFw", "colab_type": "code", "colab": {} }, "source": [ "#Idem en gardant les doublons\n", "\n", "display(dfdup.groupby(\"website\").count())\n", "display(dfdup.groupby(\"website\").mean())" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "zQAhTkQcjVno", "colab_type": "text" }, "source": [ "Les chiffres* montrent que les maisons sur immovlan sont généralement plus grandes et plus chères.\n", "\n", "\\* (le dataset est bien évidemment simulé et trop petit pour donner des résultats significatifs)\n" ] }, { "cell_type": "markdown", "metadata": { "id": "lJoxk_Rw6n02", "colab_type": "text" }, "source": [ "Nous pouvons vérifier cette observation par un test statistique (e.g., Student's t-test), avec scipy." ] }, { "cell_type": "code", "metadata": { "id": "FeoBs3AN5WM4", "colab_type": "code", "colab": {} }, "source": [ "from scipy import stats\n", "\n", "stats.ttest_ind(df[df.website == \"immoweb\"].price, df[df.website == \"immovlan\"].price)\n", "stats.f_oneway(df[df.website == \"immoweb\"].price, df[df.website == \"immovlan\"].price)\n" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "TVU7eDlG6xGy", "colab_type": "text" }, "source": [ "# Exercice: les maisons plus grandes sont-elles plus chères ?\n", "\n", "Divisez les maisons en deux groupes égaux (de part et d'autre de la surface médiane) et utilisez la méthode .describe() pour comparer les prix" ] }, { "cell_type": "code", "metadata": { "id": "4wr5EHe282QH", "colab_type": "code", "colab": {} }, "source": [ "" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "jsnDb2Go8XdJ", "colab_type": "text" }, "source": [ "## Solution" ] }, { "cell_type": "code", "metadata": { "id": "Zo-bLCZO8Y3i", "colab_type": "code", "colab": {} }, "source": [ "#df[\"large_houses\"] = df.surface > df.surface.median()\n", "#df.groupby(\"large_houses\")[\"price\"].describe()\n", "\n", "#ou: (il n'est pas nécessaire d'ajouter une colonne dans le dataframe, \n", "#il suffit de donner comme argument du groupby une series de la même longueur que le dataframe)\n", "\n", "is_large = df.surface > df.surface.median()\n", "df.groupby(is_large)[\"price\"].describe()\n", "\n", "#ou directement:\n", "df.groupby(df.surface > df.surface.median())[\"price\"].describe()" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "TF1htMvN9mnS", "colab_type": "code", "colab": {} }, "source": [ "#Anova\n", "\n", "#Pour avoir un code générique, ou extrait tous les groupes obtenus sous forme d'une liste\n", "groups = df.groupby(is_large)[\"price\"]\n", "group_list = [g[1].values for g in groups]\n", "\n", "#La méthode f_oneway prend autant d'arguments que d'échantillon à comparer. Pour transformer une liste en arguments, on utilise le symbole *\n", "stats.f_oneway(*group_list)\n" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "Ol7hZEyuFX1K", "colab_type": "text" }, "source": [ "## Sauvegarder/charger un dataframe" ] }, { "cell_type": "code", "metadata": { "id": "QMK6nKrGFbTu", "colab_type": "code", "colab": {} }, "source": [ "\n", "df.to_csv(\"houses.csv\") #tableau ascii (comma separated values)\n", "df.to_hdf(\"houses.h5\",\"df\") #\"Hierarchical Data Format\". Format standard plus générique pour les ensembles de données\n", "df.to_parquet(\"houses.parquet\") #Format plus léger (compressé) et rapide à lire pour de gros volumes de données\n" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "05Q8_ckLFw8X", "colab_type": "code", "colab": {} }, "source": [ "#Dans un notebook, on peut appeler une ligne de commande linux grâce au symbole \"!\"\n", "#le comande \"ls\" permet de lister les éléments du dossier courant. \n", "#Les lettre après le symbole \"-\" sont des options de la commande: \n", "#\"l\" permet un affichage plus détaillé, et \"h\" rend les données plus lisibles (affichage des tailles en Ko et Mo)\n", "!ls -lh" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "yaQqPhsM0sFC", "colab_type": "text" }, "source": [ "Vous pouvez également utiliser l'interface graphique de Google Colab pour accéder aux fichiers temporairement stockés dans la machine virtuelle.\n", "\n", "Vous pouvez également utiliser cette interface pour télécharger (clic-droit sur le fichier) ou importer des fichiers.\n", "\n", "
\n", "
\n", "\n", "
Accès aux fichiers dans Google Colab
\n", "
" ] }, { "cell_type": "markdown", "metadata": { "id": "7fYYGyPtwxPc", "colab_type": "text" }, "source": [ "Vous pouvez maintenant passer au [Chapitre 6: Introduction au Data Mining et à la visualisation de données](https://colab.research.google.com/github/titsitits/UNamur_Python_Analytics/blob/master/6_Data_Mining.ipynb)" ] } ] }