Skip to content

Commit

Permalink
Relecture antuki geopandas (#429)
Browse files Browse the repository at this point in the history
* Relecture KA 06/10/2023 (geopandas) (finished) (#424)

* relec 03_pandas_tutorial

* 03_geopandas_TP + install 03_geopandas_tuto

* Change ordre

* area count

* mercator

* update

* finalise projections

* remove

* names

* mise en forme

* typo chunk

---------

Co-authored-by: Kim A <kim.demarty@laposte.net>
  • Loading branch information
linogaliana and antuki committed Oct 9, 2023
1 parent ac80862 commit f8831e7
Show file tree
Hide file tree
Showing 4 changed files with 401 additions and 302 deletions.
15 changes: 9 additions & 6 deletions content/git/exogit.qmd
Expand Up @@ -145,11 +145,11 @@ les fonctionalités coeur de ces deux interfaces qui sont en fait quasi-identiqu

Les deux premières étapes se font sur `Github`.

<!-- KA : Les box d'exercice ne sont pas mises à jour dans ce doc -->

{{% box status="exercise" title="Exercice" icon="fab fa-github" %}}

**Exercice 1 : Créer un compte Github**
::: {.cell .markdown}
```{=html}
<div class="alert alert-success" role="alert">
<h3 class="alert-heading"><i class="fa-solid fa-pencil"></i> Exercice 1 : Créer un compte Github</h3>
```

1. Si vous n'en avez pas déjà un, créer un compte sur https://github.com
2. Créer un dépôt vide. Créez ce dépôt **privé**, cela permettra
Expand All @@ -158,7 +158,10 @@ après l'exercice 2, c'est comme vous le souhaitez.

*Connexion sur https://github.com/ > + (en haut de la page) > New repository > Renseigner le "Repository name" > Cocher "private" > "Create repository"*

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

## Deuxième étape: créer un *token* (jeton) HTTPS

Expand Down
103 changes: 58 additions & 45 deletions content/manipulation/03_geopandas_TP.qmd
Expand Up @@ -68,7 +68,7 @@ Illustration du principe des données spatiales (documentation de `sf`, l'équiv
[^noteQGIS]: D'ailleurs, le logiciel de cartographie spécialisé QGIS, s'appuie sur `Python`
pour les manipulations de données nécessaires avant de réaliser une carte.

Ce chapitre illustre à partir d’exemples pratiques certains principes centraux de l’analyse de données:
Ce chapitre illustre à partir d’exemples pratiques certains principes centraux de l’analyse de données :

- Manipulations sur les attributs des jeux de données ;
- Manipulations géométriques ;
Expand Down Expand Up @@ -104,25 +104,38 @@ cellule de _notebook_ `Jupyter`, le code suivant est à exécuter:
!pip install topojson
```

Les instructions d'installation du package `cartiflette`
sont quant à elles détaillées dans le chapitre
précédent.

Après installations,
les _packages_ à importer pour progresser
dans ce chapitre sont les suivants:


```{python}
#| echo: true
#| output: false
import geopandas as gpd
import contextily as ctx
import matplotlib.pyplot as plt
```

Les instructions d'installation du package `cartiflette`
sont quant à elles détaillées dans le chapitre
précédent.

```{python}
#| echo: false
#| output: false
!pip install requests py7zr geopandas openpyxl tqdm s3fs PyYAML xlrd
!pip install git+https://github.com/inseefrlab/cartiflette@80b8a5a28371feb6df31d55bcc2617948a5f9b1a
```

```{python}
#| echo: true
#| output: false
from cartiflette.s3 import download_vectorfile_url_all
```




## Lire et enrichir des données spatiales

Dans cette partie,
Expand Down Expand Up @@ -229,35 +242,33 @@ communes_borders.head()
# Il y a une colonne geometry qui contient les informations nécessaires pour connaître les contours communaux
```

A la question 3, le CRS à obtenir est:

```{python}
#| output: false
# 3) Afficher le crs
communes_borders.crs
# Les données sont en WGS84, on les reprojette en lambert 93
```

La carte du 92 est la suivante, si on ne conserve que les limites des communes :

```{python}
#| echo: false
# 4) afficher les communes du département 92
ax = communes_borders[communes_borders['INSEE_DEP'] == "92"].boundary.plot()
ax.set_axis_off()
```

Quant à Paris, à l'issue de la question 5, la même carte
aura l'aspect suivant:

```{python}
#| echo: false
# 5) Représenter la carte de Paris. Quel est le problème ?
ax = communes_borders[communes_borders['INSEE_DEP'] == "75"].boundary.plot()
ax.set_axis_off()
#On remarque ainsi facilement le problème pour Paris
#intra-muros: il manque les limites des arrondissements.
#Cela appauvrit grandement la carte de Paris.
```

On remarque ainsi facilement le problème pour Paris
intra-muros: il manque les limites des arrondissements.
Cela appauvrit grandement la carte de Paris.


```{python}
#| output: false
Expand All @@ -271,17 +282,12 @@ petite_couronne = download_vectorfile_url_all(
filter_by="DEPARTEMENT",
source="EXPRESS-COG-CARTO-TERRITOIRE",
year=2022)
petite_couronne.crs
petite_couronne = petite_couronne.to_crs(2154)
petite_couronne.crs
```

La carte de Paris intra-muros est, à l'issue de la
question 6,

```{python}
ax = petite_couronne.boundary.plot(edgecolor = "black")
ax.set_axis_off()
```


## Le système de projection

Un concept central dans les logiciels de SIG est la notion de
Expand Down Expand Up @@ -310,7 +316,7 @@ width_projected_map = screen.width/2
::: {.cell .markdown}
```{=html}
<div class="alert alert-success" role="alert">
<h3 class="alert-heading"><i class="fa-solid fa-pencil"></i> Exercice 2: Les projections, représentations et approximations</h3>
<h3 class="alert-heading"><i class="fa-solid fa-pencil"></i> Exercice 2 : Les projections, représentations et approximations</h3>
```

Voici un code utilisant encore
Expand Down Expand Up @@ -362,6 +368,7 @@ download_vectorfile_url_all(

```{python}
#| output: false
# Question 1 : Tester différentes projections
france_2154 = france.to_crs(2154)
france_healpix = france.to_crs("+proj=healpix +lon_0=0 +a=1")
france_5070 = france.to_crs(5070)
Expand Down Expand Up @@ -395,6 +402,7 @@ ax4.set_axis_off()
```

```{python}
# Question 2
france = france.to_crs(3395)
france["superficie_4326"] = france.area
france = france.to_crs(2154)
Expand Down Expand Up @@ -492,7 +500,7 @@ url = "https://opendata.paris.fr/explore/dataset/velib-emplacement-des-stations/


Dans le prochain exercice, nous proposons de créer rapidement une
carte comprenant trois couches:
carte comprenant trois couches :

- Les localisations de stations sous forme de points ;
- Les bordures des communes et arrondissements pour contextualiser ;
Expand Down Expand Up @@ -520,7 +528,7 @@ idf = download_vectorfile_url_all(
source="EXPRESS-COG-CARTO-TERRITOIRE",
year=2022)
petite_couronne_departements = idf.loc[idf['INSEE_DEP'].isin(["75","92","93","94"])]
petite_couronne_departements = idf.loc[idf['INSEE_DEP'].isin(["75","92","93","94"])].to_crs(2154)
```

::: {.cell .markdown}
Expand Down Expand Up @@ -588,6 +596,7 @@ La couche de base obtenue à l'issue de la question 4.
</summary>

```{python}
# 4. petite couronne
base = petite_couronne.boundary.plot(edgecolor = "black", linewidth = 0.5)
base
```
Expand All @@ -601,6 +610,7 @@ Puis en y ajoutant les limites départementales (question 5).
</summary>

```{python}
# 5. Ajout de la couche des départements
base = petite_couronne.boundary.plot(edgecolor = "black", linewidth = 0.5)
petite_couronne_departements.boundary.plot(ax = base, edgecolor = "blue", linewidth = 0.7)
base
Expand All @@ -615,6 +625,7 @@ Puis les stations (question 6).
</summary>

```{python}
# 6. Ajout des stations
base = petite_couronne.boundary.plot(edgecolor = "black", linewidth = 0.5)
petite_couronne_departements.boundary.plot(ax = base, edgecolor = "blue", linewidth = 0.7)
principales_stations.plot(ax= base, column = "capacity", markersize = "capacity", color = "red", alpha = 0.4)
Expand All @@ -626,6 +637,7 @@ La carte finale, après mise en forme:


```{python}
#7. sans axe et avec titre
base = petite_couronne.boundary.plot(edgecolor = "black", linewidth = 0.5)
petite_couronne_departements.boundary.plot(ax = base, edgecolor = "blue", linewidth = 0.7)
principales_stations.plot(ax= base, column = "capacity", markersize = "capacity", color = "red", alpha = 0.4)
Expand Down Expand Up @@ -657,9 +669,9 @@ sont stockées dans un _dataframe_ nommé `stations`
- les données administratives
sont dans un _dataframe_ nommé `petite_couronne`.

1. Faire une jointure spatiale pour enrichir les données de stations en y ajoutant des informations de `petite_couronne`. Appeler cet objet `stations_info`
1. Faire une jointure spatiale pour enrichir les données de stations en y ajoutant des informations de `petite_couronne`. Appeler cet objet `stations_info`.
2. Créer les objets `stations_19e` et `arrondissement_19e` pour stocker, respectivement,
les stations appartenant au 19e et les limites de l'arrondissement
les stations appartenant au 19e et les limites de l'arrondissement.
2. Représenter la carte des stations du 19e arrondissement avec le code suivant:

```python
Expand All @@ -682,18 +694,17 @@ base

```{python}
#1. Jointure spatiale entre stations et data_paris
stations = stations.to_crs(2154)
petite_couronne = petite_couronne.to_crs(2154)
stations_info = gpd.sjoin(stations, petite_couronne, predicate = 'within')
```

```{python}
#2. 19e arrondissement
stations_19 = stations_info.loc[stations_info['NOM'].str.contains("19e")]
arrondissement_19e = petite_couronne.loc[petite_couronne['NOM'].str.contains("19e")]
```

```{python}
# 3. Carto du 19e
base = petite_couronne.loc[petite_couronne['INSEE_DEP']=="75"].boundary.plot(edgecolor = "k", linewidth=0.5)
arrondissement_19e.boundary.plot(ax = base, edgecolor = "red", linewidth=0.9)
stations_19.plot(ax = base, color = "red", alpha = 0.4)
Expand All @@ -703,46 +714,48 @@ base
```



Carte obtenue à la question 4 :

```{python}
#4. Calcul et carte des capacity
stations_agg = (
stations_info
.groupby("INSEE_COG")
.agg({"stationcode": "nunique", "capacity": "sum"})
.reset_index()
)
petite_couronne['area'] = petite_couronne.area
petite_couronne_count = petite_couronne.merge(
stations_agg
).to_crs(2154)
petite_couronne_count['density'] = petite_couronne_count['area'].div(1e6)
petite_couronne_count['density'] = petite_couronne_count['capacity']*petite_couronne_count['density']
```

Carte obtenue à la question 3:

```{python}
petite_couronne_count = petite_couronne_count.loc[petite_couronne_count["INSEE_DEP"]== "75"]
aplat = petite_couronne_count.plot(
column = "capacity", cmap="coolwarm", legend=True)
aplat.set_axis_off()
aplat
```

Avec la carte de la question 3, basée sur des aplats de couleurs (choropleth map), le lecteur est victime d’une illusion classique. Les arrondissements les plus visibles sur la carte sont les plus grands. D’ailleurs c’est assez logique qu’ils soient également mieux pourvus en velib. Même si l’offre de velib est probablement plus reliée à la densité de population et d’équipements, on peut penser que l’effet taille joue et qu’ainsi on est victime d’une illusion avec la carte précédente.
Avec la carte de la question 4, basée sur des aplats de couleurs (choropleth map), le lecteur est victime d’une illusion classique. Les arrondissements les plus visibles sur la carte sont les plus grands. D’ailleurs c’est assez logique qu’ils soient également mieux pourvus en velib. Même si l’offre de velib est probablement plus reliée à la densité de population et d’équipements, on peut penser que l’effet taille joue et qu’ainsi on est victime d’une illusion avec la carte précédente.


Si on représente plutôt la capacité sous forme de densité, pour tenir compte de la taille différente des arrondissements, les conclusions sont inversées et correspondent mieux aux attentes d’un modèle centr-périphérie. Les arrondissements centraux sont mieux pourvus, cela se voit encore mieux avec des ronds proportionnels plutôt qu’une carte chorolèpthe.

Si on représente plutôt la capacité sous forme de densité, pour tenir compte de la taille différente des arrondissements, les conclusions sont inversées et correspondent mieux aux attentes d’un modèle centre-périphérie. Les arrondissements centraux sont mieux pourvus, cela se voit encore mieux avec des ronds proportionnels plutôt qu’une carte chorolèpthe.

```{python}
#5. Calcul et carte des area et density
petite_couronne_count['area'] = petite_couronne_count.area
petite_couronne_count['density'] = petite_couronne_count['area'].div(1e6)
petite_couronne_count['density'] = petite_couronne_count['capacity']*petite_couronne_count['density']
aplat = petite_couronne_count.plot(
column = "density", cmap="coolwarm", legend=True)
aplat.set_axis_off()
aplat
```


## Exercice supplémentaire

Les exercices précédents ont permis de se familiariser au traitement de données
Expand Down

0 comments on commit f8831e7

Please sign in to comment.