Skip to content

Commit

Permalink
Clean pandas tutorial and exercises (#417)
Browse files Browse the repository at this point in the history
* remove

* Manipulations de données

* update beginning

* ajoute des questions

* Ajoute des éléments

* ajoute

* correlations

* images

* clean notebook

* retire intro

* arrange

* improve notebook

* panda

* corse note retire
  • Loading branch information
linogaliana committed Oct 4, 2023
1 parent 8556b79 commit 7e03cea
Show file tree
Hide file tree
Showing 5 changed files with 638 additions and 414 deletions.
2 changes: 0 additions & 2 deletions _quarto.yml
Expand Up @@ -127,8 +127,6 @@ website:
- content/git/exogit.qmd
- section: "Contenu annexe"
contents:
- href: content/annexes/index.qmd
text: "Introduction"
- content/annexes/evaluation.qmd
- content/annexes/corrections.qmd
- href: slides/intro/index.qmd
Expand Down
166 changes: 58 additions & 108 deletions content/manipulation/02a_pandas_tutorial.qmd
Expand Up @@ -16,12 +16,12 @@ aliases: ../pandas.html
type: book
description: |
`Pandas` est l'élément central de l'écosystème `Python` pour la _data-science_.
Le succès récent de `Python` dans l'analyse de données tient beaucoup à `pandas` qui a permis d'importer la
logique `SQL` dans le langage `Python`. `pandas` embarque énormément de
fonctionalités qui permettent d'avoir des _pipelines_ efficaces pour
Le succès récent de `Python` dans l'analyse de données tient beaucoup à `Pandas` qui a permis d'importer la
logique `SQL` dans le langage `Python`. `Pandas` embarque énormément de
fonctionalités qui permettent d'avoir des chaines de traitement efficaces pour
traiter des données de volumétrie moyenne (jusqu'à quelques Gigas). Au-delà
de cette volumétrie, il faudra se tourner vers d'autres solutions
(`PostgresQL`, `Dask`, `Spark`...).
(`DuckDB`, `Dask`, `Polars`, `Spark`...).
bibliography: ../../reference.bib
image: featured.png
---
Expand All @@ -43,10 +43,13 @@ print_badges("content/manipulation/02a_pandas_tutorial.qmd")
:::

Le _package_ `Pandas` est l'une des briques centrales de l'écosystème de
la data science. Son créateur, Wes McKinney, l'a pensé comme
une surcouche à la librairie `Numpy` pour introduire le _DataFrame_
qui est un objet central dans des langages comme `R`
ou `Stata` mais qui était absent dans `Python`. `Pandas` est rapidement
la _data science_. Le _DataFrame_,
objet central dans des langages comme `R`
ou `Stata`, a longtemps était un grand absent dans l'écosystème `Python`.
Pourtant, grâce à `Numpy`, toutes les briques de base étaient présentes.
Wes McKinney, lorsqu'il a créé `Pandas` en s'appuyant sur `Pandas`
a ainsi introduit cet objet devenu banal qu'est le _DataFrame_.
`Pandas` est rapidement
devenu un incontournable de la _data-science_. L'ouvrage
de référence de @mckinney2012python présente de manière plus
ample ce _package_.
Expand All @@ -67,56 +70,12 @@ Dans ce tutoriel `Pandas`, nous allons utiliser:
* Les émissions de gaz à effet de serre estimées au niveau communal par l'ADEME. Le jeu de données est
disponible sur [data.gouv](https://www.data.gouv.fr/fr/datasets/inventaire-de-gaz-a-effet-de-serre-territorialise/#_)
et requêtable directement dans `Python` avec
[cet url](https://koumoul.com/s/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/convert)
[cet url](https://koumoul.com/s/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/convert).

Le [chapitre suivant](02b_pandas_TP) permettra de mettre en application des éléments présents dans ce chapitre avec
les données ci-dessus associées à des données de contexte au niveau communal[^1].
les données ci-dessus associées à des données de contexte au niveau communal.


::: {.cell .markdown}
[^1]: Idéalement, on utiliserait les données
[disponibles sur le site de l'Insee](https://www.insee.fr/fr/statistiques/3560121)
mais celles-ci nécessitent un peu de travail
de nettoyage qui n'entre pas dans le cadre de ce TP.

Pour faciliter l'import de données `Insee`, il est recommandé d'utiliser le package
[`Pynsee`](https://github.com/InseeFrLab/Py-Insee-Data) qui simplifie l'accès aux données
de l'Insee disponibles sur le site web [insee.fr](https://www.insee.fr/fr/accueil)
ou via des API.
:::

Pour simplifier l'accès aux données du site [insee.fr](https://www.insee.fr/fr/accueil)
nous allons utiliser un package nommé `Pynsee`.
Son code source est disponible sur
[`Github`](https://github.com/InseeFrLab/Py-Insee-Data).
Pour l'installer depuis la cellule d'un `Notebook Jupyter`:


```{python}
#| eval: false
!pip install pynsee
```

::: {.cell .markdown}
```{=html}
<div class="alert alert-info" role="alert">
<h3 class="alert-heading"><i class="fa-solid fa-comment"></i> Note</h3>
```

`pandas` offre la possibilité d'importer des données
directement depuis un url. C'est l'option prise dans ce tutoriel.

Si vous préfèrez, pour des
raisons d'accès au réseau ou de performance, importer depuis un poste local,
vous pouvez télécharger les données et changer
les commandes d'import avec le chemin adéquat plutôt que l'url.

```{=html}
</div>
```
:::

Nous suivrons les conventions habituelles dans l'import des packages
Nous suivrons les conventions habituelles dans l'import des packages:

```{python}
import numpy as np
Expand Down Expand Up @@ -145,13 +104,15 @@ pensé certes pour les utilisateurs d'[`Observable Javascript`](https://observab
mais qui offre de nombreux exemples intéressants pour les afficionados de `Pandas` ;
* La _cheatsheet suivante_, [issue de ce post](https://becominghuman.ai/cheat-sheets-for-ai-neural-networks-machine-learning-deep-learning-big-data-678c51b4b463)

![Cheasheet pandas](https://cdn-images-1.medium.com/max/2000/1*YhTbz8b8Svi22wNVvqzneg.jpeg)

## Logique de pandas
![Cheasheet `Pandas`](https://cdn-images-1.medium.com/max/2000/1*YhTbz8b8Svi22wNVvqzneg.jpeg){width=70%}

L'objet central dans la logique `pandas` est le `DataFrame`.
## Logique de `Pandas`

L'objet central dans la logique `Pandas` est le `DataFrame`.
Il s'agit d'une structure particulière de données
à deux dimensions, structurées en alignant des lignes et colonnes. Les colonnes
à deux dimensions, structurées en alignant des lignes et colonnes.
Contrairement à une matrice, les colonnes
peuvent être de type différent.

Un `DataFrame` est composé des éléments suivants:
Expand All @@ -160,8 +121,6 @@ Un `DataFrame` est composé des éléments suivants:
* le nom de la colonne ;
* la valeur de la donnée ;

Structuration d'un DataFrame pandas,
empruntée à <https://medium.com/epfl-extension-school/selecting-data-from-a-pandas-dataframe-53917dc39953>:

```{python}
#| include: false
Expand All @@ -175,9 +134,10 @@ with open('featured.png', 'wb') as out_file:
shutil.copyfileobj(response.raw, out_file)
```

![](featured.png)
![Structuration d'un _DataFrame_ `Pandas`,
empruntée à <https://medium.com/epfl-extension-school/selecting-data-from-a-pandas-dataframe-53917dc39953>](featured.png)

Le concept de *tidy* data, popularisé par Hadley Wickham via ses packages `R`,
Le concept de __*tidy*__ data, popularisé par Hadley Wickham via ses packages `R`,
est parfaitement pertinent pour décrire la structure d'un `DataFrame pandas`.
Les trois règles sont les suivantes:

Expand All @@ -190,47 +150,33 @@ se trouve sur une unique cellule.
![Concept de tidy data (emprunté à H. Wickham)](https://d33wubrfki0l68.cloudfront.net/6f1ddb544fc5c69a2478e444ab8112fb0eea23f8/91adc/images/tidy-1.png)


::: {.cell .markdown}
```{=html}
<div class="alert alert-warning" role="alert">
<h3 class="alert-heading"><i class="fa-solid fa-lightbulb"></i> Hint</h3>
```
Concernant la syntaxe, une partie des commandes `Python` est inspirée par la logique `SQL`.
On retrouvera ainsi une philosophie proche de celle du SQL où on fait des opérations
de sélection de ligne ou de colonne. Voici une illustration de quelques manipulations de données
que nous mettrons en oeuvre par la suite:

Les `DataFrames` sont assez rapides en `Python`[^2] et permettent de traiter en local de manière efficace des tables de
données comportant plusieurs millions d'observations (en fonction de la configuration de l'ordinateur)
et dont la volumétrie peut être conséquente (plusieurs centaines
de Mo). Néanmoins, passé un certain seuil, qui dépend de la puissance de la machine mais aussi de la complexité
de l'opération effectuée, le DataFrame `pandas` peut montrer certaines limites. Dans ce cas, il existe différentes
solutions: `Dask` (dataframe aux opérations parallélisés), `SQL` (notamment `Postgres`),
`Spark` (solution _big data_). Un chapitre spécial de ce cours est consacré à `Dask`.
::: {layout-ncol=2}

```{=html}
</div>
```
:::
![Sélectionner des colonnes](select_pandas.png)
![Renommer des colonnes](rename_pandas.png)

![Créer de nouvelles colonnes](mutate_pandas.png)
![Sélectionner des lignes](filter_pandas.png)

![Réordonner le _DataFrame_](arrange_pandas.png)

::: {.cell .markdown}
[^2]: En `R`, les deux formes de dataframes qui se sont imposées récemment sont les `tibbles` (package `dplyr`)
et les `data.tables` (package `data.table`). `dplyr` reprend la syntaxe `SQL` de manière relativement
transparente ce qui rend la syntaxe très proche de celle de `pandas`. Cependant,
alors que `dplyr` supporte très mal les données dont la volumétrie dépasse 1Go, `pandas` s'en
accomode bien. Les performances de `pandas` sont plus proches de celles de `data.table`, qui est
connu pour être une approche efficace avec des données de taille importante.
:::

Concernant la syntaxe, une partie des commandes python est inspirée par la logique `SQL`. On retrouvera ainsi
des instructions relativement transparentes.

`Pandas` propose énormément de fonctionnalités pré-implémentées.
Il est vivement recommandé, avant de se lancer dans l'écriture d'une
fonction, de se poser la question de son implémentation native dans `numpy`, `pandas`, etc.
En particulier, la plupart du temps, s'il existe une solution implémentée dans une librairie, il convient
de l'utiliser.
fonction, de se poser la question de son implémentation native dans `Numpy`, `Pandas`, etc.
La plupart du temps, s'il existe une solution implémentée dans une librairie, il convient
de l'utiliser car elle sera plus efficace que celle que vous mettrez en oeuvre.

## Les Series
## Les `Series`

En fait, un DataFrame est une collection d'objets appelés `pandas.Series`.
En fait, un _DataFrame_ est une collection d'objets appelés `pandas.Series`.
Ces `Series` sont des objets d'une dimension qui sont des extensions des
array-unidimensionnels `numpy`. En particulier, pour faciliter le traitement
de données catégorielles ou temporelles, des types de variables
Expand Down Expand Up @@ -459,13 +405,6 @@ nom l'indique, de n'afficher que les dernières lignes
* `sample` qui permet d'afficher un échantillon aléatoire de *n* lignes.
Cette méthode propose de nombreuses options.

::: {.cell .markdown}
[^3]: Il est préférable d'utiliser la fonction `display` (ou tout simplement
taper le nom du `DataFrame`) qu'utiliser la fonction `print`. Le
`display` des objets `pandas` est assez esthétique, contrairement à `print`
qui renvoie du texte brut.
:::

::: {.cell .markdown}
```{=html}
<div class="alert alert-danger" role="alert">
Expand Down Expand Up @@ -549,14 +488,10 @@ Voici un premier résumé, accompagné d'un comparatif avec `R`
| Opération | pandas | dplyr (`R`) | data.table (`R`) |
|-------------------------------|--------------|----------------|----------------------------|
| Récupérer le nom des colonnes | `df.columns` | `colnames(df)` | `colnames(df)` |
| Récupérer les indices[^4] | `df.index` | |`unique(df[,get(key(df))])` |
| Récupérer les dimensions | `df.shape` | `c(nrow(df), ncol(df))` | `c(nrow(df), ncol(df))` |
| Récupérer les indices | `df.index` | |`unique(df[,get(key(df))])` |
| Récupérer les dimensions | `df.shape` | `dim(df)` | `dim(df)` |
| Récupérer le nombre de valeurs uniques d'une variable | `df['myvar'].nunique()` | `df %>% summarise(distinct(myvar))` | `df[,uniqueN(myvar)]` |

::: {.cell .markdown}
[^4]: Le principe d'indice n'existe pas dans `dplyr`. Ce qui s'approche le plus des indices, au sens de
`pandas`, sont les *clés* en `data.table`.
:::

### Statistiques agrégées

Expand Down Expand Up @@ -773,7 +708,7 @@ df_example
L'objectif du [TP pandas](#pandasTP) est de se familiariser plus avec ces
commandes à travers l'exemple des données des émissions de C02.

Les opérations les plus fréquentes en SQL `sont` résumées par le tableau suivant.
Les opérations les plus fréquentes en `SQL` sont résumées par le tableau suivant.
Il est utile de les connaître (beaucoup de syntaxes de maniement de données
reprennent ces termes) car, d'une
manière ou d'une autre, elles couvrent la plupart
Expand All @@ -788,6 +723,21 @@ des usages de manipulation des données
| Effectuer une opération par groupe | `GROUP BY` | `df.groupby('Commune').mean()` | `df %>% group_by(Commune) %>% summarise(m = mean)` | `df[,mean(Commune), by = Commune]` |
| Joindre deux bases de données (*inner join*) | `SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.x` | `table1.merge(table2, left_on = 'id', right_on = 'x')` | `table1 %>% inner_join(table2, by = c('id'='x'))` | `merge(table1, table2, by.x = 'id', by.y = 'x')` |

Quelques uns de ces concepts illustrés:

::: {layout-ncol=2}

![Sélectionner des colonnes](select_pandas.png)
![Renommer des colonnes](rename_pandas.png)

![Créer de nouvelles colonnes](mutate_pandas.png)
![Sélectionner des lignes](filter_pandas.png)

![Réordonner le _DataFrame_](arrange_pandas.png)

:::


### Opérations sur les colonnes: `select`, `mutate`, `drop`

Les `DataFrames` pandas sont des objets *mutables* en langage `Python`,
Expand Down Expand Up @@ -958,7 +908,7 @@ L'image suivante, issue de
représente bien la manière dont fonctionne l'approche
`split`-`apply`-`combine`

![Split-apply-combine](https://unlhcc.github.io/r-novice-gapminder/fig/12-plyr-fig1.png)
![Split-apply-combine](https://unlhcc.github.io/r-novice-gapminder/fig/12-plyr-fig1.png){fig-width=70%}


Ce [tutoriel](https://realpython.com/pandas-groupby/) sur le sujet
Expand Down

0 comments on commit 7e03cea

Please sign in to comment.