{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# TME sur les données blablacar\n", "\n", "**Ce fichier est le fichier de travail**, l'autre fichier blablacar est donné pour information et pour montrer comment les données ont été collectées." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "%matplotlib notebook\n", "import pickle as pkl" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Chargement des données\n", "\n", "Les données sont stockées au format pickle (code fourni ci-dessous):\n", "\n", "1. Importer le module : import `pickle as pkl`\n", "1. Charger les données avec `load`\n", "1. La structure est un dictionnaire, les données sont dans le champ `data`\n", "1. La description des colonnes est dans `indexcol`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# chargement des données\n", "fich = pkl.load( open('donnees_blablacar.pkl', 'rb'))\n", "\n", "# {'indexcol': cols , 'data':pp2db, 'villes': villes, 'marques':marques }\n", "titles_col = fich['indexcol']\n", "print(len(titles_col), titles_col) \n", "data = fich['data']\n", "print(data.shape)\n", "dico_villes = fich['villes']\n", "dico_marques = fich['marques']\n", "print(dico_marques)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Discrétisation et histogramme\n", "\n", "Nous nous intéressons à la variable `distance` (dernière colonne). Nous allons procéder de la manière suivante:\n", "1. Analyse rapide de la variable aléatoire: calcul de la moyenne et de l'écart-type\n", "1. Analyse plus fine (1): affichage des 10 quantiles\n", "1. Analyse plus fine (2): discrétisation de la variable en 10 intervalles de largeur constante & comptage des effectifs dans chaque catégorie (= construction d'un histogramme)\n", " - Construire l'histogramme à la main. (1) calculer les bornes des intervalles puis (2) utiliser `np.where` pour déterminer les effectifs dans chaque classe. Utiliser `plt.bar` pour l'affichage.\n", " - Vérifier vos résultats avec `np.histogram` et `plt.hist` pour l'affichage\n", " - Comparer les quantiles et les bornes des intervalles discrets\n", "1. Discuter le nombre d'intervalles pour l'histogramme et trouver une valeur satisfaisante\n", "\n", "**Notes** : \n", "- dans `np.where`, il faut mettre des parenthèses s'il y a plusieurs clause\n", "\n", "> `np.where((x>a) & (x\n", "> `np.where((x>a) & (x `plt.imshow(p_dm, interpolation='nearest')`\n", ">\n", "> `plt.show()`\n", "- la variable `marque` est bruitée. Vous pourrez vous amuser à éliminer ou fusionner certaines catégories\n", "- les indices dans une matrice doivent toujours être entiers. `int(...)`\n", "- pour ajouter une description sur l'axe des x:\n", "```python\n", "fig, ax = plt.subplots(1,1)\n", "plt.imshow(p_dsm, interpolation='nearest')\n", "ax.set_xticks(np.arange(len(dico_marques)))\n", "ax.set_xticklabels(dico_marques.keys(),rotation=90,fontsize=8)\n", "plt.show()\n", "```\n", "- Si l'image est trop petite pour voir quelque chose: solution = sauvegarde en pdf (ie vectorielle) + ouverture avec un logiciel de lecture pdf\n", "```python\n", "plt.savefig('mafigure.pdf')\n", "```\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# loi jointe distance / marque\n", "\n", "# construction de la distance discrétisée \n", "# Dimensions : = (Nind x 1) = mêmes dimensions que d\n", "# contenu = catégorie de distance (entre 0 et 29 par exemple si on a discrétisé en 30 catégories)\n", "dd = np.zeros(d.shape)\n", "\n", "# remplissage avec np.where\n", "\n", "p_dm = np.zeros((len(bornes)-1, len(dico_marques)))\n", "\n", "# remplissage de la matrice p_dm = double boucle + comptage\n", "\n", "p_dm /= p_dm.sum() # normalisation\n", "\n", "# affichage du résultat\n", "plt.imshow(p_dm, interpolation='nearest')\n", "plt.show()\n", " " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# loi conditionnelle distance | marque\n", "# calcul d'une marginale\n", "\n", "p_m = \n", "\n", "# calcul de la conditionnelle\n", "p_dsm = \n", "\n", "# affichage\n", "fig, ax = plt.subplots(1,1)\n", "plt.imshow(p_dsm, interpolation='nearest')\n", "ax.set_xticks(np.arange(len(dico_marques)))\n", "ax.set_xticklabels(dico_marques.keys(),rotation=90,fontsize=8)\n", "plt.show()\n", "\n", "# proposition d'un critère très rapide pour vérifier qu'il s'agit bien d'une distribution conditionnelle\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Tracé de l'ensemble de l'échantillon avec des codes couleurs\n", "\n", "Nous proposons ensuite de tracer toutes les trajectoires des voitures blablacar. Pour cela, il faut utiliser la commande `plt.plot`.\n", "Vous devez optenir des étoiles à partir des 7 villes requêtes: `['Paris', 'Marseille', 'Grenoble', 'Lille', 'Strasbourg', 'Nantes', 'Bordeaux']`.\n", "Mais on ne voit pas grand chose... Et ça prend beaucoup de temps à tracer avec une boucle for. On propose donc une série d'exercice pour mieux comprendre ce qui se passe.\n", "1. Attention à l'ordre des arguments dans le plot:\n", "```plt.plot(tous_les_x, tous_les_y)```\n", "Afin de tracer des trajectoires, il faut envoyer les x et les y 2 par 2 dans une boucle `for`\n", "1. Pour éviter les boucles, il existe une méthode `quiver` dédiée au tracé de champs de vecteurs: ça ira beaucoup plus vite qu'avec plot. Il faut juste bien comprendre les mécanismes d'échelles. Pour utiliser l'échelle 1, la commande est la suivante:\n", "```python\n", "plt.quiver(x_dep, y_dep, delta_x, delta_y,\\\n", " angles='xy', scale_units='xy', scale=1)\n", "```\n", "1. Isoler les trajets proposés à partir de chacune des villes sachant les coordonnées sont:\n", "```python\n", "coord = np.array([[45.18721767, 5.72345183],\n", " [47.22572172, -1.56558993],\n", " [50.63010695, 3.07071992],\n", " [48.5782548, 7.74078742],\n", " [44.83848889, -0.58156509],\n", " [43.2991509, 5.38925024],\n", " [48.8477201, 2.34607889]])\n", "```\n", "Chaque trajectoire (point de départ) sera rattachée à la ville la plus proche.\n", "Une fois la distance calculée pour chaque origine de trajectoire, vous pourrez avoir besoin de `argmin`\n", "1. Tracer les trajets d'une couleur spéciale en fonction des origines. \n", "\n", "Les commandes matplotlib attendent des instructions de couleur au format RGB ou avec des lettres. Je vous propose une solution élégante pour distinguer les villes.\n", " - soit l'index de la ville la plus proche sotcké dans `ville_or` (0,...,7)\n", " - construire le dictionnaire: `dict({0:'b', 1:'r', 2:'k', 3:'y', 4:'c', 5:'m', 6:'g'})`\n", " - transformer `ville_or` en `ville_c` en vectorisant l'appel à la table de hash:\n", "```python\n", "ville_c = np.vectorize(dico.get)(ville_or)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# tracé de l'ensemble des trajectoires avec un code couleur en fonction de la ville de départ\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# trouver l'information sur la ville la plus proche\n", "\n", "coord = np.array([[45.18721767, 5.72345183],\n", " [47.22572172, -1.56558993],\n", " [50.63010695, 3.07071992],\n", " [48.5782548, 7.74078742],\n", " [44.83848889, -0.58156509],\n", " [43.2991509, 5.38925024],\n", " [48.8477201, 2.34607889]])\n", "\n", "# calcul de la matrice de distance\n", "dist = \n", "# indice de la ville d'origine du trajet (plus petite distance dans le tableau ci-dessus)\n", "ville_or = \n", "\n", "# astuce pour construire une correspondance indice => code couleur\n", "dico = dict({0:'b', 1:'r', 2:'k', 3:'y', 4:'c', 5:'m', 6:'g'})\n", "ville_c = np.vectorize(dico.get)(ville_or)\n", "\n", "plt.figure()\n", "plt.quiver([... coordonnées des vecteurs ...]\\\n", " color= ville_c, angles='xy', scale_units='xy', scale=1)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Etude de la corrélation entre variables\n", "\n", "On propose d'étudier la corrélation entre la distance du trajet et le nombre d'étoiles de confort. Attention, les étoiles ne sont pas toujours renseignées (-1 = inconnu). On fera aussi ces opérations entre la distance et le prix.\n", "\n", "1. Tracer dans le plan les coordonnées (distance,etoile) pour les points concernés\n", "\n", "Vous utiliserez la commande `scatter` pour réaliser l'opération\n", "1. Calculer le coefficient de corrélation entre les deux variables aléatoires\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# test de corrélation entre la distance et le confort de la voiture\n", "plt.figure()\n", "# affichage du nuage de points correspondant au deux variables\n", "plt.show()\n", "\n", "# calcul du coefficient de corrélation pour tous les points admissibles \n", "# (ceux pour lesquels les étoiles sont renseignées)\n", "\n", "# test de corrélation entre la distance et le prix\n", "plt.figure()\n", "# affichage du nuage de points correspondant au deux variables\n", "plt.show()\n", "\n", "# calcul du coefficient de corrélation pour tous les points admissibles \n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Quelques questions supplémentaires\n", "\n", "### prix au kilomètre en fonction de l'origine\n", "On s'intérroge sur le prix des courses en fonction des villes de départ. On ne veut pas tomber dans des pièges liés à des résumés simplistes, nous allons donc calculer la distribution jointe (prix_km, ville_origine).\n", "1. Mettre au propre le code de discretisation en construisant une méthode de signature:\n", "```python\n", "def discretisation(x, nintervalles):\n", " #[...]\n", " return bornes, effectifs, xd \n", "```\n", "1. Mettre au propre le code de calcul de la loi jointe entre deux échantillons de variables aléatoires discrètes\n", "```python\n", "def pjointe(xd, yd):\n", " #[...]\n", " return pj\n", "```\n", "1. En l'état, nous avons du mal à analyser les données. Ceci est du aux valeurs extrêmes (notamment hautes). Afin de rendre l'analyse robuste, seuiller le prix au km au 99ème percentile (toutes les valeurs supérieures sont ramenées à cette valeur limite).\n", "1. Proposer quelques analyses.\n", "\n", "### même analyse pour voir dans quelle ville les gens sont plus matinaux, s'ils partent plus vers le sud ou le nord, l'est ou l'ouest...\n", "\n", "Si vous étiez un journaliste en manque de sujet de reportage, quel(s) graphique(s) calculeriez vous à partir de ces données? \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def discretisation(x, nintervalles, eps = 0.0000001) :\n", " # [...]\n", " return bornes, effectifs, xd\n", "\n", "def pjointe(xd, yd): # variable codées de 0 à valmax\n", " # [...]\n", " return pj" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# prix km\n", "pkm = data[:,-4]/data[:,-1]\n", "n = 30 # nb catégories\n", "\n", "# robustesse : calcul du 99è percentile et seuillage des valeurs\n", "\n", "bornes, effectifs, pkmd = discretisation(pkm, n)\n", "\n", "pj = pjointe(pkmd,ville_or)\n", "\n", "pv = # calcul de la marginale\n", "p_km_s_v = # calcul de la conditionnelle\n", "\n", "fig, ax = plt.subplots(1,1)\n", "plt.imshow(p_km_s_v, interpolation='nearest')\n", "plt.show()\n", "\n", "# analyses" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "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.6.0" } }, "nbformat": 4, "nbformat_minor": 2 }