"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "JndnmDMp66FL"
},
"source": [
"#### Copyright 2017 Google LLC."
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"cellView": "both",
"colab": {},
"colab_type": "code",
"collapsed": true,
"id": "hMqWDc_m6rUC"
},
"outputs": [],
"source": [
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
"# you may not use this file except in compliance with the License.\n",
"# You may obtain a copy of the License at\n",
"#\n",
"# https://www.apache.org/licenses/LICENSE-2.0\n",
"#\n",
"# Unless required by applicable law or agreed to in writing, software\n",
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
"# See the License for the specific language governing permissions and\n",
"# limitations under the License."
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "rHLcriKWLRe4"
},
"source": [
" # Présentation rapide de Pandas - *version modifée*"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "QvJBqX8_Bctk"
},
"source": [
"**Objectifs d'apprentissage :**\n",
" * Introduction aux structures de données `DataFrame` et `Series` de la bibliothèque *Pandas*\n",
" * Accéder aux données et les manipuler dans une structure `DataFrame` et `Series`\n",
" * Importer des données d'un fichier CSV dans un `DataFrame` *Pandas*\n",
" * Réindexer un `DataFrame` pour mélanger les données"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "TIFJ83ZTBctl"
},
"source": [
" [*Pandas*](http://pandas.pydata.org/) est une API d'analyse de données orientée colonnes. C'est un excellent outil pour manipuler et analyser des données d'entrée. Beaucoup de frameworks d'apprentissage automatique acceptent les structures de données *Pandas* en entrée.\n",
"Il faudrait des pages et des pages pour présenter de manière exhaustive l'API *Pandas*, mais les concepts fondamentaux sont relativement simples. Aussi, nous avons décidé de vous les exposer ci-dessous. Pour une description plus complète, vous pouvez consulter le [site de documentation de *Pandas*](http://pandas.pydata.org/pandas-docs/stable/index.html), sur lequel vous trouverez de multiples informations ainsi que de nombreux didacticiels."
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "s_JOISVgmn9v"
},
"source": [
" ## Concepts de base\n",
"\n",
"Les lignes de code suivantes permettent d'installer *matplotlib* et *pandas* "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install matplotlib\n",
"%matplotlib inline\n",
"!pip install pandas"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"La ligne de code suivante permet d'importer l'API *pandas* et d'afficher sa version :"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 35
},
"colab_type": "code",
"id": "aSRYu62xUi3g",
"outputId": "092dd1c9-f333-4bc3-b9a9-9848724b7f6b"
},
"outputs": [
{
"data": {
"text/plain": [
"'0.24.2'"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import pandas as pd\n",
"pd.__version__"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "daQreKXIUslr"
},
"source": [
" On distingue deux grandes catégories de structures de données *Pandas* :\n",
"\n",
" * Le **`DataFrame`**, un tableau relationnel de données, avec des lignes et des colonnes étiquetées\n",
" * La **`Series`**, constituée d'une seule colonne. Un `DataFrame` contient une ou plusieurs `Series`, chacune étant étiquetée.\n",
"\n",
"Le DataFrame est une abstraction fréquemment utilisée pour manipuler des données. [Spark](https://spark.apache.org/) et [R](https://www.r-project.org/about.html) proposent des implémentations similaires."
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "fjnAk1xcU0yc"
},
"source": [
" Pour créer une `Series`, vous pouvez notamment créer un objet `Series`. Par exemple :"
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 88
},
"colab_type": "code",
"id": "DFZ42Uq7UFDj",
"outputId": "55107013-1e7c-4fdd-ba8f-5cafc9f66661"
},
"outputs": [
{
"data": {
"text/plain": [
"0 San Francisco\n",
"1 San Jose\n",
"2 Sacramento\n",
"dtype: object"
]
},
"execution_count": 3,
"metadata": {
"tags": []
},
"output_type": "execute_result"
}
],
"source": [
"pd.Series(['San Francisco', 'San Jose', 'Sacramento'])"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "U5ouUp1cU6pC"
},
"source": [
" Il est possible de créer des objets `DataFrame` en transmettant un `dictionnaire` qui met en correspondance les noms de colonnes (des `chaînes de caractères`) avec leur `Series` respective. Lorsque la longueur de la `Series` ne correspond pas, les valeurs manquantes sont remplacées par des valeurs [NA/NaN](http://pandas.pydata.org/pandas-docs/stable/missing_data.html) spéciales. Exemple :"
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 143
},
"colab_type": "code",
"id": "avgr6GfiUh8t",
"outputId": "8a83a621-5c57-40f7-c247-72a265961910"
},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
City name
\n",
"
Population
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
San Francisco
\n",
"
852469
\n",
"
\n",
"
\n",
"
1
\n",
"
San Jose
\n",
"
1015785
\n",
"
\n",
"
\n",
"
2
\n",
"
Sacramento
\n",
"
485199
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" City name Population\n",
"0 San Francisco 852469\n",
"1 San Jose 1015785\n",
"2 Sacramento 485199"
]
},
"execution_count": 4,
"metadata": {
"tags": []
},
"output_type": "execute_result"
}
],
"source": [
"city_names = pd.Series(['San Francisco', 'San Jose', 'Sacramento'])\n",
"population = pd.Series([852469, 1015785, 485199])\n",
"\n",
"pd.DataFrame({ 'City name': city_names, 'Population': population })"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "oa5wfZT7VHJl"
},
"source": [
" Le plus souvent, vous chargez un fichier entier dans un `DataFrame`. Dans l'exemple qui suit, le fichier chargé contient des données immobilières pour la Californie. Exécutez la cellule suivante pour charger les données et définir les caractéristiques :"
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 320
},
"colab_type": "code",
"id": "av6RYOraVG1V",
"outputId": "a7cac740-ed05-4806-a6b1-7412eca1f5a4"
},
"outputs": [
{
"data": {
"text/html": [
"
"
],
"text/plain": [
" City name Population\n",
"0 San Francisco 852469\n",
"1 San Jose 1015785"
]
},
"execution_count": 12,
"metadata": {
"tags": []
},
"output_type": "execute_result"
}
],
"source": [
"print(type(cities[0:2]))\n",
"cities[0:2]"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "65g1ZdGVjXsQ"
},
"source": [
" *Pandas* propose en outre une API extrêmement riche, avec des fonctions avancées d'[indexation et de sélection](http://pandas.pydata.org/pandas-docs/stable/indexing.html), que nous ne pouvons malheureusement pas aborder ici dans le détail."
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "RM1iaD-ka3Y1"
},
"source": [
" ## Manipuler des données\n",
"\n",
"Il est possible d'effectuer des opérations arithmétiques de base de Python sur les `Series`. Par exemple :"
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 88
},
"colab_type": "code",
"id": "XWmyCFJ5bOv-",
"outputId": "5c0f7d56-3779-4593-ab20-5c618313fa4a"
},
"outputs": [
{
"data": {
"text/plain": [
"0 852.469\n",
"1 1015.785\n",
"2 485.199\n",
"dtype: float64"
]
},
"execution_count": 13,
"metadata": {
"tags": []
},
"output_type": "execute_result"
}
],
"source": [
"population / 1000."
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "TQzIVnbnmWGM"
},
"source": [
" [NumPy](http://www.numpy.org/) est un kit d'outils de calculs scientifiques populaire. Les `Series` *Pandas* peuvent faire office d'arguments pour la plupart des fonctions NumPy :"
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {},
"colab_type": "code",
"collapsed": true,
"id": "ko6pLK6JmkYP"
},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"np.log(population)"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "xmxFuQmurr6d"
},
"source": [
" La méthode `Series.apply` convient pour les transformations à une colonne plus complexes. Comme la [fonction `map`](https://docs.python.org/2/library/functions.html#map) de Python, elle accepte en argument une [fonction `lambda`](https://docs.python.org/2/tutorial/controlflow.html#lambda-expressions), appliquée à chaque valeur.\n",
"\n",
"L'exemple ci-dessous permet de créer une `Series` signalant si la `population` dépasse ou non un million d'habitants :"
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 88
},
"colab_type": "code",
"id": "Fc1DvPAbstjI",
"outputId": "8a1cd4e7-c299-4e02-a592-092743858b1a"
},
"outputs": [
{
"data": {
"text/plain": [
"0 False\n",
"1 True\n",
"2 False\n",
"dtype: bool"
]
},
"execution_count": 14,
"metadata": {
"tags": []
},
"output_type": "execute_result"
}
],
"source": [
"population.apply(lambda val: val > 1000000)"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "ZeYYLoV9b9fB"
},
"source": [
" \n",
"La modification des `DataFrames` est également très simple. Ainsi, le code suivant permet d'ajouter deux `Series` à un `DataFrame` existant :"
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 143
},
"colab_type": "code",
"id": "0gCEX99Hb8LR",
"outputId": "d2ef5874-d75f-4f5c-aa7d-3bfda406a4ad"
},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
City name
\n",
"
Population
\n",
"
Area square miles
\n",
"
Population density
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
San Francisco
\n",
"
852469
\n",
"
46.87
\n",
"
18187.945381
\n",
"
\n",
"
\n",
"
1
\n",
"
San Jose
\n",
"
1015785
\n",
"
176.53
\n",
"
5754.177760
\n",
"
\n",
"
\n",
"
2
\n",
"
Sacramento
\n",
"
485199
\n",
"
97.92
\n",
"
4955.055147
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" City name Population Area square miles Population density\n",
"0 San Francisco 852469 46.87 18187.945381\n",
"1 San Jose 1015785 176.53 5754.177760\n",
"2 Sacramento 485199 97.92 4955.055147"
]
},
"execution_count": 15,
"metadata": {
"tags": []
},
"output_type": "execute_result"
}
],
"source": [
"cities['Area square miles'] = pd.Series([46.87, 176.53, 97.92])\n",
"cities['Population density'] = cities['Population'] / cities['Area square miles']\n",
"cities"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "6qh63m-ayb-c"
},
"source": [
" ## Exercice n° 1\n",
"\n",
"Modifiez le tableau `cities` en ajoutant une colonne booléenne qui prend la valeur True si et seulement si les *deux* conditions suivantes sont remplies :\n",
"\n",
" * La ville porte le nom d'un saint.\n",
" * La ville s'étend sur plus de 50 miles carrés.\n",
"\n",
"**Remarque** : Pour combiner des `Series` booléennes, utilisez des opérateurs de bits, pas les opérateurs booléens classiques. Par exemple, pour le *ET logique*, utilisez `&` au lieu de `and`.\n",
"\n",
"**Astuce** : En espagnol, \"San\" signifie \"saint\"."
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {},
"colab_type": "code",
"collapsed": true,
"id": "zCOn8ftSyddH"
},
"outputs": [],
"source": [
"# Your code here"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "YHIWvc9Ms-Ll"
},
"source": [
" ### Solution\n",
"\n",
"Cliquez ci-dessous pour afficher la solution."
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {},
"colab_type": "code",
"collapsed": true,
"id": "T5OlrqtdtCIb"
},
"outputs": [],
"source": [
"cities['Is wide and has saint name'] = (cities['Area square miles'] > 50) & cities['City name'].apply(lambda name: name.startswith('San'))\n",
"cities"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "f-xAOJeMiXFB"
},
"source": [
" ## Index\n",
"Les objets `Series` et `DataFrame` définissent également une propriété `index`, qui affecte un identifiant à chaque élément d'une `Series` ou chaque ligne d'un `DataFrame`. \n",
"\n",
"Par défaut, *Pandas* affecte les valeurs d'index en suivant l'ordre des données source. Ces valeurs ne varient pas par la suite ; elles restent inchangées en cas de réagencement des données."
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {},
"colab_type": "code",
"collapsed": true,
"id": "2684gsWNinq9"
},
"outputs": [],
"source": [
"city_names.index"
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {},
"colab_type": "code",
"collapsed": true,
"id": "F_qPe2TBjfWd"
},
"outputs": [],
"source": [
"cities.index"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "hp2oWY9Slo_h"
},
"source": [
" Appelez `DataFrame.reindex` pour réorganiser manuellement les lignes. Le code suivant, par exemple, revient à trier les données par nom de ville :"
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {},
"colab_type": "code",
"collapsed": true,
"id": "sN0zUzSAj-U1"
},
"outputs": [],
"source": [
"cities.reindex([2, 0, 1])"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "-GQFz8NZuS06"
},
"source": [
" La réindexation est un excellent moyen de mélanger (organiser aléatoirement) les données d'un `DataFrame`. Dans l'exemple ci-dessous, l'index de type tableau est transmis à la fonction NumPy `random.permutation`, qui mélange les valeurs. En appelant `reindex` avec ce tableau mélangé, nous mélangeons également les lignes du `DataFrame`.\n",
"Exécutez plusieurs fois la cellule suivante !"
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {},
"colab_type": "code",
"collapsed": true,
"id": "mF8GC0k8uYhz"
},
"outputs": [],
"source": [
"cities.reindex(np.random.permutation(cities.index))"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "fSso35fQmGKb"
},
"source": [
" Pour en savoir plus, consultez la [documentation relative aux index](http://pandas.pydata.org/pandas-docs/stable/indexing.html#index-objects)."
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "8UngIdVhz8C0"
},
"source": [
" ## Exercice n° 2\n",
"\n",
"La méthode `reindex` autorise les valeurs d'index autres que celles associées au `DataFrame` d'origine. Voyez ce qu'il se passe lorsque vous utilisez ce type de valeurs ! Pourquoi est-ce autorisé à votre avis ?"
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {},
"colab_type": "code",
"collapsed": true,
"id": "PN55GrDX0jzO"
},
"outputs": [],
"source": [
"# Your code here"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "TJffr5_Jwqvd"
},
"source": [
" ### Solution\n",
"\n",
"Cliquez ci-dessous pour afficher la solution."
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "8oSvi2QWwuDH"
},
"source": [
" Lorsque le tableau d'entrée `reindex` contient des valeurs d'index ne faisant pas partie de la liste des index du `DataFrame` d'origine, `reindex` ajoute des lignes pour ces index \\'manquants\\' et insère la valeur `NaN` dans les colonnes correspondantes :"
]
},
{
"cell_type": "code",
"execution_count": 0,
"metadata": {
"colab": {},
"colab_type": "code",
"collapsed": true,
"id": "yBdkucKCwy4x"
},
"outputs": [],
"source": [
"cities.reindex([0, 4, 5, 2])"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "2l82PhPbwz7g"
},
"source": [
" Ce comportement est souhaitable, car les index sont souvent des chaînes de caractères extraites des données réelles. La [documentation *Pandas* sur la fonction `reindex`](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.reindex.html) inclut un exemple avec des noms de navigateurs comme valeurs d'index).\n",
"\n",
"Dans ce cas, autoriser les index \\'manquants\\' facilite la réindexation à l'aide d'une liste externe, car vous n'avez pas à vous préoccuper de l'intégrité des données d'entrée."
]
}
],
"metadata": {
"colab": {
"collapsed_sections": [
"JndnmDMp66FL",
"YHIWvc9Ms-Ll",
"TJffr5_Jwqvd"
],
"include_colab_link": true,
"name": "Copie de intro_to_pandas.ipynb",
"provenance": [],
"version": "0.3.2"
},
"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.1"
}
},
"nbformat": 4,
"nbformat_minor": 1
}