Skip to content

Commit badc492

Browse files
authored
Finalize geopandas section (#48)
Encore le problème des figures (#29)
1 parent edca391 commit badc492

File tree

5 files changed

+127
-40
lines changed

5 files changed

+127
-40
lines changed

config.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ theme="hugo-theme-techdoc"
66
enableGitInfo = true
77
enableEmoji = true
88

9+
ignoreFiles = ["\\.Rmd$", "\\.Rmarkdown$", "_files$", "_cache$"]
10+
911
disableToc = false
1012

1113
[markup.goldmark.renderer]

content/manipulation/03_geopandas.Rmd

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,35 +25,52 @@ slug: geopandas
2525
library(knitr)
2626
library(reticulate)
2727
knitr::knit_engines$set(python = reticulate::eng_python)
28+
# knitr::opts_knit$set(#fig.path = '../../static/Rmdoutput/manipulation',
29+
# root.dir = '../../static/Rmdoutput/manipulation'#,
30+
# #base.dir = '../../static/Rmdoutput/manipulation'#,
31+
# #output.dir = '../../static/Rmdoutput/manipulation'
32+
# )
2833
```
2934

3035
```{python, include = FALSE}
3136
import os
3237
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = 'C:/Users/W3CRK9/AppData/Local/r-miniconda/envs/r-reticulate/Library/plugins/platforms'
38+
os.environ["PROJ_LIB"] = r'C:\Users\W3CRK9\AppData\Local\r-miniconda\pkgs\proj4-4.9.3-hfa6e2cd_9\Library\share'
39+
#os.environ['GDAL_DATA'] = "C:/Users/W3CRK9/AppData/Local/gdal-3-1-2/bin/gdal-data"
3340
```
3441

3542
Dans ce tutoriel, nous allons utiliser:
3643

3744
<!----
3845
* [Réseau de pistes cyclables de la ville de Paris](https://opendata.paris.fr/explore/dataset/reseau-cyclable/table/?disjunctive.typologie_simple&disjunctive.bidirectionnel&disjunctive.statut&disjunctive.sens_velo&disjunctive.voie&disjunctive.arrdt&disjunctive.bois&disjunctive.position&disjunctive.circulation&disjunctive.piste&disjunctive.couloir_bus&disjunctive.type_continuite&disjunctive.reseau&basemap=jawg.streets&location=12,48.85943,2.3493)
3946
------>
40-
* [Carte des limites administratives françaises]()
47+
48+
* [Localisations des stations velib](https://opendata.paris.fr/explore/dataset/velib-emplacement-des-stations/download/?format=geojson&timezone=Europe/Berlin&lang=fr)
49+
* [Carte des limites administratives françaises](https://www.data.gouv.fr/fr/datasets/r/07b7c9a2-d1e2-4da6-9f20-01a7b72d4b12)
50+
* [Arrondissements parisiens](https://opendata.paris.fr/explore/dataset/arrondissements/download/?format=geojson&timezone=Europe/Berlin&lang=fr)
4151

4252
La représentation des données, notamment la cartographie, est présentée plus
4353
amplement dans la partie [visualiser](visualiser).
4454

45-
Ce tutoriel s'inspire beaucoup d'un autre tutoriel que j'ai fait pour R **lien utilitR**. Il peut servir de pendant à celui-ci pour l'utilisateur de `R`.
55+
Ce tutoriel s'inspire beaucoup d'un autre tutoriel que j'ai fait pour
56+
R disponible [ici](https://linogaliana.gitlab.io/documentationR/spatdata.html).
57+
Il peut servir de pendant à celui-ci pour l'utilisateur de `R`.
4658

4759

4860
```{python}
4961
import geopandas as gpd
50-
#import contextily as ctx
62+
import contextily as ctx
5163
```
5264

5365

5466
## Données spatiales: quelle différence avec des données traditionnelles ?
5567

56-
**Le terme "données spatiales" désigne les données qui portent sur les caractéristiques géographiques des objets (localisation, contours, liens)**. Les caractéristiques géographiques des objets sont décrites à l'aide d'un **système de coordonnées** qui permetent une représentation dans un espace euclidien ($(x,y)$). Le passage de l'espace réel (la Terre, qui est une sphère) à l'espace plan se fait grâce à un **système de projection**. Voici quelques exemples de données spatiales:
68+
**Le terme "données spatiales" désigne les données
69+
qui portent sur les caractéristiques géographiques des objets (localisation, contours, liens)**. Les caractéristiques géographiques des objets sont décrites à l'aide d'un **système de coordonnées**
70+
qui permettent une représentation dans un espace euclidien ($(x,y)$).
71+
Le passage de l'espace réel (la Terre, qui est une sphère) à l'espace plan
72+
se fait grâce à un **système de projection**. Voici quelques exemples
73+
de données spatiales:
5774

5875
* Une table décrivant des bâtiments, avec les coordonnées géographiques de chaque bâtiment;
5976
* Le découpage communal du territoire, avec le contour du territoire de chaque commune;
@@ -243,7 +260,7 @@ communes['dep'] = communes.insee.str[:2]
243260
ax = stations.sample(200).plot(figsize = (10,10), color = 'red', alpha = 0.4, zorder=2)
244261
communes[communes['dep'].isin(['75','92','93','94'])].plot(ax = ax, zorder=1, edgecolor = "black", facecolor="none",
245262
color = None)
246-
# ctx.add_basemap(ax, crs = stations.crs.to_string(), source = ctx.providers.Stamen.Watercolor)
263+
#ctx.add_basemap(ax, crs = stations.crs.to_string(), source = ctx.providers.Stamen.Watercolor)
247264
```
248265

249266
### Opérations sur les attributs
@@ -324,7 +341,7 @@ departement['geometry'] = departement['geometry'].centroid
324341
ax = departement.plot(figsize = (10,10), color = 'red', alpha = 0.4, zorder=2)
325342
communes[communes['dep'] == "31"].plot(ax = ax, zorder=1, edgecolor = "black", facecolor="none",
326343
color = None)
327-
#ctx.add_basemap(ax, crs = stations.crs.to_string(), source = #ctx.providers.Stamen.Toner)
344+
#ctx.add_basemap(ax, crs = stations.crs.to_string(), source = ctx.providers.Stamen.Toner)
328345
```
329346

330347

@@ -334,16 +351,18 @@ Précédemment, nous avons appliqué une méthode `to_crs` pour reprojeter
334351
les données dans un système de projection différent de celui du fichier
335352
d'origine:
336353

337-
```{python, eval = FALSE}
354+
```{python, eval = TRUE}
338355
communes = communes.to_crs(2154)
339356
stations = stations.to_crs(2154)
340357
```
341358

342359

343-
Le système de projection est fondamental pour que la dimension spatiale soit bien interprétée par `python`. Un mauvais système de représentation
360+
Le système de projection est fondamental pour que la dimension
361+
spatiale soit bien interprétée par `python`. Un mauvais système de représentation
344362
fausse l'appréciation visuelle mais peut aussi entraîner des erreurs dans
345363
les calculs sur la dimension spatiale.
346-
Ce [post](https://www.earthdatascience.org/courses/earth-analytics/spatial-data-r/geographic-vs-projected-coordinate-reference-systems-UTM/) propose de riches éléments sur le sujet, notamment l'image suivante qui montre bien le principe d'une projection:
364+
Ce [post](https://www.earthdatascience.org/courses/earth-analytics/spatial-data-r/geographic-vs-projected-coordinate-reference-systems-UTM/) propose de riches éléments sur le
365+
sujet, notamment l'image suivante qui montre bien le principe d'une projection:
347366

348367
![Les différents types de projection](https://www.earthdatascience.org/images/courses/earth-analytics/spatial-data/spatial-projection-transformations-crs.png)
349368

@@ -377,15 +396,15 @@ communes = communes.set_crs(2154)
377396

378397
Alors que la reprojection (projection Albers: 5070) s'obtient de la manière suivante:
379398

380-
```{python, eval = FALSE}
399+
```{python, eval = TRUE}
381400
communes[communes.dep != "97"].dissolve(by='dep', aggfunc='sum').to_crs(5070).plot()
382401
```
383402

384403
On le voit, cela modifie totalement la représentation de l'objet dans l'espace.
385404
Clairement, cette projection n'est pas adaptée aux longitudes et lattitudes françaises. C'est normal, il s'agit d'une projection adaptée au continent
386405
nord-américain, et encore, pas dans son ensemble :
387406

388-
```{python, eval = FALSE}
407+
```{python, eval = TRUE}
389408
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
390409
world[world.continent == "North America"].to_crs(5070).plot(alpha = 0.2, edgecolor = "k")
391410
```
@@ -403,16 +422,16 @@ La seule différence avec `pandas` est dans la dimension géographique.
403422
Si on désire conserver la dimension géographique, il faut faire
404423
attention à faire:
405424

406-
```python
425+
~~~~python
407426
geopandas_object.merge(pandas_object)
408-
```
427+
~~~~
409428

410429
Si on utilise deux objets géographiques mais ne désire conserver qu'une seule
411430
dimension géographique^[1], on fera
412431

413-
```python
432+
~~~~python
414433
geopandas_object1.merge(geopandas_object2)
415-
```
434+
~~~~
416435

417436
Seule la géométrie de l'objet de gauche
418437
sera conservée, même si on fait un *right join*.

content/manipulation/03_geopandas.md

Lines changed: 56 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,34 @@ Dans ce tutoriel, nous allons utiliser:
3030
<!----
3131
* [Réseau de pistes cyclables de la ville de Paris](https://opendata.paris.fr/explore/dataset/reseau-cyclable/table/?disjunctive.typologie_simple&disjunctive.bidirectionnel&disjunctive.statut&disjunctive.sens_velo&disjunctive.voie&disjunctive.arrdt&disjunctive.bois&disjunctive.position&disjunctive.circulation&disjunctive.piste&disjunctive.couloir_bus&disjunctive.type_continuite&disjunctive.reseau&basemap=jawg.streets&location=12,48.85943,2.3493)
3232
------>
33-
* [Carte des limites administratives françaises]()
33+
34+
* [Localisations des stations velib](https://opendata.paris.fr/explore/dataset/velib-emplacement-des-stations/download/?format=geojson&timezone=Europe/Berlin&lang=fr)
35+
* [Carte des limites administratives françaises](https://www.data.gouv.fr/fr/datasets/r/07b7c9a2-d1e2-4da6-9f20-01a7b72d4b12)
36+
* [Arrondissements parisiens](https://opendata.paris.fr/explore/dataset/arrondissements/download/?format=geojson&timezone=Europe/Berlin&lang=fr)
3437

3538
La représentation des données, notamment la cartographie, est présentée plus
3639
amplement dans la partie [visualiser](visualiser).
3740

38-
Ce tutoriel s'inspire beaucoup d'un autre tutoriel que j'ai fait pour R **lien utilitR**. Il peut servir de pendant à celui-ci pour l'utilisateur de `R`.
41+
Ce tutoriel s'inspire beaucoup d'un autre tutoriel que j'ai fait pour
42+
R disponible [ici](https://linogaliana.gitlab.io/documentationR/spatdata.html).
43+
Il peut servir de pendant à celui-ci pour l'utilisateur de `R`.
3944

4045

4146

4247
```python
4348
import geopandas as gpd
44-
#import contextily as ctx
49+
import contextily as ctx
4550
```
4651

4752

4853
## Données spatiales: quelle différence avec des données traditionnelles ?
4954

50-
**Le terme "données spatiales" désigne les données qui portent sur les caractéristiques géographiques des objets (localisation, contours, liens)**. Les caractéristiques géographiques des objets sont décrites à l'aide d'un **système de coordonnées** qui permetent une représentation dans un espace euclidien ($(x,y)$). Le passage de l'espace réel (la Terre, qui est une sphère) à l'espace plan se fait grâce à un **système de projection**. Voici quelques exemples de données spatiales:
55+
**Le terme "données spatiales" désigne les données
56+
qui portent sur les caractéristiques géographiques des objets (localisation, contours, liens)**. Les caractéristiques géographiques des objets sont décrites à l'aide d'un **système de coordonnées**
57+
qui permettent une représentation dans un espace euclidien ($(x,y)$).
58+
Le passage de l'espace réel (la Terre, qui est une sphère) à l'espace plan
59+
se fait grâce à un **système de projection**. Voici quelques exemples
60+
de données spatiales:
5161

5262
* Une table décrivant des bâtiments, avec les coordonnées géographiques de chaque bâtiment;
5363
* Le découpage communal du territoire, avec le contour du territoire de chaque commune;
@@ -259,7 +269,7 @@ communes['dep'] = communes.insee.str[:2]
259269
ax = stations.sample(200).plot(figsize = (10,10), color = 'red', alpha = 0.4, zorder=2)
260270
communes[communes['dep'].isin(['75','92','93','94'])].plot(ax = ax, zorder=1, edgecolor = "black", facecolor="none",
261271
color = None)
262-
# ctx.add_basemap(ax, crs = stations.crs.to_string(), source = ctx.providers.Stamen.Watercolor)
272+
#ctx.add_basemap(ax, crs = stations.crs.to_string(), source = ctx.providers.Stamen.Watercolor)
263273
```
264274

265275
![](03_geopandas_files/figure-html/unnamed-chunk-5-1.png)<!-- -->
@@ -277,9 +287,9 @@ stations.describe()
277287

278288
```
279289
## capacity
280-
## count 1397.000000
281-
## mean 31.404438
282-
## std 12.149572
290+
## count 1398.000000
291+
## mean 31.403433
292+
## std 12.145281
283293
## min 0.000000
284294
## 25% 23.000000
285295
## 50% 29.000000
@@ -327,11 +337,11 @@ communes[communes.dep != "97"].sort_values('surf_ha', ascending = False)
327337
## 32467 49092 Chemillé-en-Anjou ... NaN 49
328338
## 28877 49228 Noyant-Villages ... NaN 49
329339
## ... ... ... ... ... ...
330-
## 15 75113 NaN ... 13.0 75
331-
## 16 75109 NaN ... 9.0 75
332-
## 17 75118 NaN ... 18.0 75
333-
## 18 75111 NaN ... 11.0 75
334-
## 19 75116 NaN ... 16.0 75
340+
## 15 75101 NaN ... 1.0 75
341+
## 16 75102 NaN ... 2.0 75
342+
## 17 75119 NaN ... 19.0 75
343+
## 18 75115 NaN ... 15.0 75
344+
## 19 75112 NaN ... 12.0 75
335345
##
336346
## [34870 rows x 13 columns]
337347
```
@@ -394,11 +404,17 @@ fera
394404
departement = communes[communes.dep == "31"].copy()
395405
departement['geometry'] = departement['geometry'].centroid
396406

407+
```
408+
409+
```
410+
## C:/Users/W3CRK9/AppData/Local/r-miniconda/envs/r-reticulate/python.exe:1: UserWarning: Geometry is in a geographic CRS. Results from 'centroid' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.
411+
```
397412

413+
```python
398414
ax = departement.plot(figsize = (10,10), color = 'red', alpha = 0.4, zorder=2)
399415
communes[communes['dep'] == "31"].plot(ax = ax, zorder=1, edgecolor = "black", facecolor="none",
400416
color = None)
401-
#ctx.add_basemap(ax, crs = stations.crs.to_string(), source = #ctx.providers.Stamen.Toner)
417+
#ctx.add_basemap(ax, crs = stations.crs.to_string(), source = ctx.providers.Stamen.Toner)
402418
```
403419

404420
![](03_geopandas_files/figure-html/unnamed-chunk-11-1.png)<!-- -->
@@ -417,10 +433,12 @@ stations = stations.to_crs(2154)
417433
```
418434

419435

420-
Le système de projection est fondamental pour que la dimension spatiale soit bien interprétée par `python`. Un mauvais système de représentation
436+
Le système de projection est fondamental pour que la dimension
437+
spatiale soit bien interprétée par `python`. Un mauvais système de représentation
421438
fausse l'appréciation visuelle mais peut aussi entraîner des erreurs dans
422439
les calculs sur la dimension spatiale.
423-
Ce [post](https://www.earthdatascience.org/courses/earth-analytics/spatial-data-r/geographic-vs-projected-coordinate-reference-systems-UTM/) propose de riches éléments sur le sujet, notamment l'image suivante qui montre bien le principe d'une projection:
440+
Ce [post](https://www.earthdatascience.org/courses/earth-analytics/spatial-data-r/geographic-vs-projected-coordinate-reference-systems-UTM/) propose de riches éléments sur le
441+
sujet, notamment l'image suivante qui montre bien le principe d'une projection:
424442

425443
![Les différents types de projection](https://www.earthdatascience.org/images/courses/earth-analytics/spatial-data/spatial-projection-transformations-crs.png)
426444

@@ -443,7 +461,20 @@ communes.crs
443461
```
444462

445463
```
446-
## {'init': 'epsg:4326'}
464+
## <Projected CRS: EPSG:2154>
465+
## Name: RGF93 / Lambert-93
466+
## Axis Info [cartesian]:
467+
## - X[east]: Easting (metre)
468+
## - Y[north]: Northing (metre)
469+
## Area of Use:
470+
## - name: France
471+
## - bounds: (-9.86, 41.15, 10.38, 51.56)
472+
## Coordinate Operation:
473+
## - name: Lambert-93
474+
## - method: Lambert Conic Conformal (2SP)
475+
## Datum: Reseau Geodesique Francais 1993
476+
## - Ellipsoid: GRS 1980
477+
## - Prime Meridian: Greenwich
447478
```
448479

449480
Les deux principales méthodes pour définir le système de projection utilisé sont:
@@ -465,6 +496,8 @@ Alors que la reprojection (projection Albers: 5070) s'obtient de la manière sui
465496
communes[communes.dep != "97"].dissolve(by='dep', aggfunc='sum').to_crs(5070).plot()
466497
```
467498

499+
![](03_geopandas_files/figure-html/unnamed-chunk-15-1.png)<!-- -->
500+
468501
On le voit, cela modifie totalement la représentation de l'objet dans l'espace.
469502
Clairement, cette projection n'est pas adaptée aux longitudes et lattitudes françaises. C'est normal, il s'agit d'une projection adaptée au continent
470503
nord-américain, et encore, pas dans son ensemble :
@@ -475,6 +508,8 @@ world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
475508
world[world.continent == "North America"].to_crs(5070).plot(alpha = 0.2, edgecolor = "k")
476509
```
477510

511+
![](03_geopandas_files/figure-html/unnamed-chunk-16-1.png)<!-- -->
512+
478513

479514
## Joindre des données
480515

@@ -488,16 +523,16 @@ La seule différence avec `pandas` est dans la dimension géographique.
488523
Si on désire conserver la dimension géographique, il faut faire
489524
attention à faire:
490525

491-
```python
526+
~~~~python
492527
geopandas_object.merge(pandas_object)
493-
```
528+
~~~~
494529

495530
Si on utilise deux objets géographiques mais ne désire conserver qu'une seule
496531
dimension géographique^[1], on fera
497532

498-
```python
533+
~~~~python
499534
geopandas_object1.merge(geopandas_object2)
500-
```
535+
~~~~
501536

502537
Seule la géométrie de l'objet de gauche
503538
sera conservée, même si on fait un *right join*.

content/manipulation/03_geopandas_tp.Rmd

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,13 @@ knitr::opts_chunk$set(eval = FALSE, include = FALSE, echo = FALSE)
3131
```{python, include = FALSE}
3232
import os
3333
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = 'C:/Users/W3CRK9/AppData/Local/r-miniconda/envs/r-reticulate/Library/plugins/platforms'
34+
os.environ["PROJ_LIB"] = r'C:\Users\W3CRK9\AppData\Local\r-miniconda\pkgs\proj4-4.9.3-hfa6e2cd_9\Library\share'
35+
#os.environ['GDAL_DATA'] = "C:/Users/W3CRK9/AppData/Local/gdal-3-1-2/bin/gdal-data"
3436
```
3537

38+
```{python, echo = TRUE}
39+
import geopandas as gpd
40+
```
3641

3742

3843
# Lire et enrichir des données spatiales
@@ -147,7 +152,6 @@ Cette [page](https://geopandas.org/mapping.html#maps-with-layers) peut vous aide
147152
```{python}
148153
url = "https://opendata.paris.fr/explore/dataset/velib-emplacement-des-stations/download/?format=geojson&timezone=Europe/Berlin&lang=fr"
149154
stations = gpd.read_file(url)
150-
151155
```
152156

153157
```{python}
@@ -205,14 +209,33 @@ data_paris.merge(stations_agg, how = 'inner', suffixes = [None, '_agg']).plot(co
205209
```{python}
206210
df = data_paris.merge(stations_agg, how = 'inner', suffixes = [None, '_agg'])
207211
cols = ['stationcode','capacity']
208-
df = df[[s + '_density' for s in cols]] = df[cols].div(df.to_crs(2158).area*10**(-6), axis = 0)
212+
df[[s + '_density' for s in cols]] = df[cols].div(df.to_crs(2158).area*10**(-6), axis = 0)
209213
df.plot(column = 'capacity_density', cmap = 'RdYlBu_r')
210214
df.plot(column = 'capacity_density', cmap = 'plasma_r')
211215
```
212216

213217
**Exercice 5 (optionnel): Relier distance au métro et capacité d'une station**
214218

215-
1. Relier chaque station velib à la station de transport en commun la plus proche
219+
Une aide [ici](https://pysal.org/scipy2019-intermediate-gds/deterministic/gds1-relations.html#how-about-nearest-neighbor-joins)
220+
221+
1. Relier chaque station velib à la station de transport en commun la plus proche. Vous pouvez
222+
prendre les localisations des stations [ici](https://data.iledefrance-mobilites.fr/explore/dataset/traces-du-reseau-ferre-idf/download/?format=geojson&timezone=Europe/Berlin&lang=fr)
216223
2. Quelle ligne de transport est à proximité du plus de velib ?
217224
3. Calculer la distance de chaque station à la ligne de métro la plus proche. Faire un nuage de points reliant distance au métro et nombre de places en stations
218225

226+
```{python}
227+
stations_transport = gpd.read_file("https://data.ratp.fr/explore/dataset/positions-geographiques-des-stations-du-reseau-ratp/download/?format=geojson&timezone=Europe/Berlin&lang=fr")
228+
```
229+
230+
```{python, eval = FALSE}
231+
# un truc comme ça à revoir mais là fait des NaN :'(
232+
from shapely.ops import nearest_points
233+
temp = stations_transport.unary_union
234+
235+
def find_nearest(geometry1, geometry2 = temp, df_point2 = stations_transport):
236+
nearest = nearest_points(geometry1, geometry2)[1]
237+
return df_point2[df_point2['geometry'] == nearest][:1]['nomptar']
238+
239+
stations['Nearest'] = stations.apply(lambda row: find_nearest(row.geometry), axis=1)
240+
```
241+

0 commit comments

Comments
 (0)