Skip to content

Commit

Permalink
pynsee pour importer des données Insee 🚀 (#127)
Browse files Browse the repository at this point in the history
* utilise pynsee

* reformat exo

* Automated changes

* Automated changes

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
linogaliana and github-actions[bot] committed Aug 31, 2021
1 parent e351975 commit 4a317e3
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 31 deletions.
27 changes: 19 additions & 8 deletions content/course/manipulation/02a_pandas_tutorial.Rmd
Expand Up @@ -75,10 +75,20 @@ 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
et requêtable directement dans `Python` avec
[cet url](https://koumoul.com/s/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/convert)
* Quelques données de contexte au niveau communal. Idéalement, on utiliserait les données
[disponibles sur le site de l'Insee](https://www.insee.fr/fr/statistiques/3560121). Pour faciliter l'import de celles-ci, les données ont été mises à disposition dans le dépôt github, [sur cet url](https://github.com/linogaliana/python-datascientist/blob/pandas_intro/data/filosofi_2016.csv)

Le chapitre suivant 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].


[^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.


:warning: `pandas` offre la possibilité d'importer des données
Expand All @@ -94,6 +104,7 @@ Nous suivrons les conventions habituelles dans l'import des packages
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pynsee.download
```

Pour obtenir des résultats reproductibles, on peut fixer la racine du générateur
Expand Down Expand Up @@ -456,7 +467,7 @@ Voici un premier résumé des méthodes `pandas` utiles, et un comparatif avec `
| Récupérer les dimensions | `df.shape` | `c(nrow(df), ncol(df))` | `c(nrow(df), ncol(df))` |
| Récupérer le nombre de valeurs uniques d'une variable | `df['myvar'].nunique()` | `df %>% summarise(distinct(myvar))` | `df[,uniqueN(myvar)]` |

^[3]: Le principe d'indice n'existe pas dans `dplyr`. Ce qui s'approche le plus des indices, au sens de
[^3]: 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`.


Expand Down Expand Up @@ -535,7 +546,7 @@ On trouvera aussi la référence à `isna()` qui est la même méthode que `isnu
# Graphiques rapides

Les méthodes par défaut de graphique
(approfondies dans la partie visualisation **LIEN A AJOUTER**)
(approfondies dans la [partie visualisation](#visualisation))
sont pratiques pour
produire rapidement un graphique, notament après des opérations
complexes de maniement de données.
Expand Down Expand Up @@ -756,7 +767,7 @@ résidentiel consomme le plus.

## Filtrer

L'opération de sélection de lignes s'appelle `FILTER` en SQL et s'utilise
L'opération de sélection de lignes s'appelle `FILTER` en SQL. Elle s'utilise
en fonction d'une condition logique (clause `WHERE`). On sélectionne les
données sur une condition logique. Il existe plusieurs méthodes en `pandas`.

Expand Down Expand Up @@ -860,7 +871,7 @@ du DataFrame de sortie. Si on avait utilisé plusieurs variables de groupe,
on obtiendrait un objet multi-indexé. Sur la gestion des `multiindex`, on
pourra se référer à la référence de `Modern pandas` donnée en fin de cours.

Tant qu'on appelle pas une action sur un DataFrame par groupe, du type
Tant qu'on n'appelle pas une action sur un DataFrame par groupe, du type
`head` ou `display`, `pandas` n'effectue aucune opération. On parle de
*lazy evaluation*. Par exemple, le résultat de `df.groupby('dep')` est
une transformation qui n'est pas encore évaluée:
Expand Down Expand Up @@ -940,7 +951,7 @@ serions dans une situation, beaucoup plus complexe, d'appariement flou).
La situation typique est l'appariement entre deux sources de données selon un identifiant
individuel. Ici, il s'agit d'un identifiant de code commune.

Il est recommandé de lire [ce guide assez complet sur la question des jointures avec R](https://linogaliana.gitlab.io/documentationR/joindre-des-tables-de-donn%C3%A9es.html) qui donne des recommandations également utiles en `python`.
Il est recommandé de lire [ce guide assez complet sur la question des jointures avec R](https://www.book.utilitr.org/jointures.html) qui donne des recommandations également utiles en `python`.

On utilise de manière indifférente les termes *merge* ou *join*.
Le deuxième terme provient de la syntaxe SQL.
Expand Down
81 changes: 58 additions & 23 deletions content/course/manipulation/02b_pandas_TP.Rmd
Expand Up @@ -37,30 +37,47 @@ knitr::opts_chunk$set(echo = FALSE)
```


Dans ce tutoriel `pandas`, nous allons utiliser:
Dans ce tutoriel `pandas`, nous allons utiliser deux sources de données :

* 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)
* Quelques données de contexte au niveau communal. Idéalement, on utiliserait les données
[disponibles sur le site de l'Insee](https://www.insee.fr/fr/statistiques/3560121). Pour faciliter l'import de celles-ci, les données ont été mises à disposition dans le dépôt github, [sur cet url](https://github.com/linogaliana/python-datascientist/blob/pandas_intro/data/filosofi_2016.csv)


`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.

* 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.

{{% panel status="note" title="Note" icon="fa fa-comment" %}}
Pour installer `pynsee` depuis le [dépôt Github](https://github.com/InseeFrLab/Py-Insee-Data), il est nécessaire
de taper, dans une invite de commande,

```shell
pip install git+https://github.com/InseeFrLab/Py-Insee-Data@master
```

{{% /panel %}}

[^1]: Toute contribution sur ce package, disponible sur [Github](https://github.com/InseeFrLab/Py-Insee-Data) est bienvenue !

Nous suivrons les conventions habituelles dans l'import des packages


```{python}
```{python, echo = TRUE}
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pynsee.download
```

## Exploration de la structure des données
Expand All @@ -71,13 +88,17 @@ Commencer par importer les données de l'Ademe à l'aide du package `pandas`. Vo
df = pd.read_csv("https://koumoul.com/s/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/convert")
```

Pour les données de cadrage au niveau communal (source Insee), une version arrangée et facile à requêter est fournie sur [github](https://github.com/linogaliana/python-datascientist/blob/pandas_intro/data/filosofi_2016.csv)
Pour les données de cadrage au niveau communal (source Insee), le package `pynsee` facilite grandement la vie.
La liste des données disponibles est [ici](https://inseefrlab.github.io/DoReMIFaSol/articles/donnees_dispo.html).
En l'occurrence, on va utiliser les données Filosofi (données de revenu) au niveau communal.
Le code pour télécharger celle-ci est le suivant

```{python}
df_city = pd.read_csv("https://raw.githubusercontent.com/linogaliana/python-datascientist/master/data/filosofi_2016.csv")
```{python, echo = TRUE}
df_city = pynsee.download.telechargerDonnees("FILOSOFI_COM", date = "dernier")
```

-----------------
{{% panel status="exercise" title="Exercise" icon="fas fa-pencil-alt" %}}

**Exercice 1: Afficher des données**

L'objectif de cet exercice est de vous amener à afficher des informations sur les données dans un bloc de code (notebook) ou dans la console
Expand All @@ -91,7 +112,8 @@ Commencer sur `df`:

Faire la même chose sur `df_city`

------------------
{{% /panel %}}


```{python, show = FALSE, include = FALSE}
df.head(10)
Expand All @@ -114,7 +136,8 @@ df_city[:6].sample(n = 100, replace = True, weights = [0.5] + [0.1]*5)
Cette première approche exploratoire donne une idée assez précise de la manière dont les données sont organisées. On remarque ainsi une différence entre `df` et `df_city` quant aux valeurs manquantes: la première base est relativement complète, la seconde comporte beaucoup de valeurs manquantes. Autrement dit, si on désire exploiter `df_city`, il faut faire attention à la variable choisie.


----------------------
{{% panel status="exercise" title="Exercise" icon="fas fa-pencil-alt" %}}

**Exercice 2: structure des données**

La première chose à vérifier est le format des données, afin d'identifier des types de variables qui ne conviennent pas. Ici, comme c'est `pandas` qui a géré automatiquement les types de variables, il y a peu de chances que les types ne soient pas adéquats mais une vérification ne fait pas de mal.
Expand All @@ -135,7 +158,8 @@ On se focalise temporairement sur les observations où le libellé comporte plus
* Vérifier sur les grandes villes (plus de 100 000 personnes), la proportion de villes où libellés et codes communes ne coïncident pas. Identifier ces observations.
* Vérifier dans `df_city` les villes dont le libellé est égal à Montreuil. Vérifier également celles qui contiennent le terme 'Saint-Denis'

-----------------------
{{% /panel %}}


```{python, include = FALSE, eval = FALSE}
df.dtypes
Expand Down Expand Up @@ -187,7 +211,8 @@ Ce petit exercice permet de se rassurer car les libellés dupliqués sont en fai
Les indices sont des éléments spéciaux d'un DataFrame puisqu'ils permettent d'identifier certaines observations. Il est tout à fait possible d'utiliser plusieurs indices, par exemple si on a des niveaux imbriqués.


----------------------
{{% panel status="exercise" title="Exercise" icon="fas fa-pencil-alt" %}}

**Exercice 3: Les indices**

A partir de l'exercice précédent, on peut se fier aux codes communes.
Expand All @@ -197,7 +222,8 @@ A partir de l'exercice précédent, on peut se fier aux codes communes.
* Calculer les émissions totales par secteur pour chaque département. Mettre en log ces résultats dans un objet `df_log`. Garder 5 départements et produire un barplot
* Repartir de `df`. Calculer les émissions totales par département et sortir la liste des 10 principaux émetteurs de CO2 et des 5 départements les moins émetteurs. Sans faire de *merge*, regarder les caractéristiques de ces départements (population et niveau de vie)

-------------------------
{{% /panel %}}


```{python, include = FALSE, eval = FALSE}
df = df.set_index('INSEE commune')
Expand Down Expand Up @@ -234,7 +260,8 @@ df_city[df_city['dep'].isin(petits_emetteurs.index)][['NBPERSMENFISC16','MED16']
df_city[df_city['dep'].isin(petits_emetteurs.index)][['NBPERSMENFISC16','MED16']].mean()
```

-------------------------
{{% panel status="exercise" title="Exercise" icon="fas fa-pencil-alt" %}}

**Exercice 4: performance des indices**

Un des intérêts des indices est qu'il permettent des agrégations efficaces.
Expand All @@ -243,7 +270,8 @@ Un des intérêts des indices est qu'il permettent des agrégations efficaces.
* Utiliser la variable `dep` comme indice pour `df_copy` et retirer tout index pour `df_copy2`
* Importer le module `timeit` et comparer le temps d'exécution de la somme par secteur, pour chaque département, des émissions de CO2

---------------------------
{{% /panel %}}


```{python, include = FALSE, eval = FALSE}
df_copy = df.copy()
Expand Down Expand Up @@ -280,15 +308,17 @@ L'aide mémoire suivante aidera à se rappeler les fonctions à appliquer si bes

Le fait de passer d'un format *wide* au format *long* (ou vice-versa) peut être extrêmement pratique car certaines fonctions sont plus adéquates sur une forme de données ou sur l'autre. En règle générale, avec `python` comme avec `R`, les formats *long* sont souvent préférables.

----------------------------
{{% panel status="exercise" title="Exercise" icon="fas fa-pencil-alt" %}}

**Exercice 5: Restructurer les données: wide to long**

* Créer une copie des données de l'ADEME en faisant `df_wide = df.copy()`
* Restructurer les données au format *long* pour avoir des données d'émissions par secteur en gardant comme niveau d'analyse la commune (attention aux autres variables identifiantes).
* Faire la somme par secteur et représenter graphiquement
* Garder, pour chaque département, le secteur le plus polluant

--------------------------------
{{% /panel %}}



```{python, include = FALSE, eval = FALSE}
Expand All @@ -306,7 +336,8 @@ df_wide.reset_index().melt(id_vars = ['INSEE commune','Commune','dep'],
)
```

-----------------------------------
{{% panel status="exercise" title="Exercise" icon="fas fa-pencil-alt" %}}

**Exercice 6: long to wide**

Cette transformation est moins fréquente car appliquer des fonctions par groupe, comme nous le verrons par la suite, est très simple.
Expand All @@ -317,7 +348,8 @@ Cette transformation est moins fréquente car appliquer des fonctions par groupe
* Calculer, pour chaque secteur, la place du département dans la hiérarchie des émissions nationales
* A partir de là, en déduire le rang médian de chaque département dans la hiérarchie des émissions et regarder les 10 plus mauvais élèves, selon ce critère.

---------------------------------
{{% /panel %}}


```{python, include = FALSE, eval = FALSE}
df_wide = df.copy()
Expand All @@ -339,15 +371,18 @@ On utilise de manière indifférente les termes *merge* ou *join*. Le deuxième

![](../02a_pandas_tutorial/pandas_join.png)

------------------------------------

{{% panel status="exercise" title="Exercise" icon="fas fa-pencil-alt" %}}

**Exercice 7: Calculer l'empreinte carbone par habitant**

* Créer une variable `emissions` qui correspond aux émissions totales d'une commune
* Faire une jointure à gauche entre les données d'émissions et les données de cadrage. Comparer les émissions moyennes des villes sans *match* (celles dont des variables bien choisies de la table de droite sont NaN) avec celles où on a bien une valeur correspondante dans la base Insee
* Faire un *inner join* puis calculer l'empreinte carbone dans chaque commune. Sortir un histogramme en niveau puis en log et quelques statistiques descriptives sur le sujet.
* Regarder la corrélation entre les variables de cadrage et l'empreinte carbone. Certaines variables semblent expliquer l'empreinte carbone ?

--------------------------------------------
{{% /panel %}}


```{python, include = FALSE, eval = FALSE}
df['emissions'] = df.sum(axis = 1)
Expand Down

0 comments on commit 4a317e3

Please sign in to comment.