# Manipulation de données spatiales dans R avec le package`SF` ![](https://i.imgur.com/N7bEhZA.png) Le package `sf` (Spatial Feature) est dédié à la manipulation, la transformation et l'analyse de données spatiales. A la manière du Tidyverse, il combine les fonctionnalités de `sp`, `rgeos` et `rgdal` dans un package. > Une attention particulière a été portée à la compatibilité du package avec la syntaxe pipe et les opérateurs du tidyverse. > ``` install.packages("sf") library(sf) ``` Ressources : * https://r-spatial.github.io/sf/ * https://geocompr.robinlovelace.net/geometric-operations.html * https://rcarto.github.io/carto_avec_r/chapitre1.html ***Cheatsheet*** > https://github.com/rstudio/cheatsheets/blob/master/sf.pdf ![](https://i.imgur.com/5p1NdEe.png) ![](https://i.imgur.com/4DFhFOw.png) ___ ## Importer un shapefile ``` ardt <- st_read(dsn = "C:/Users/Xo/Desktop/GeoDATA/arrondissements.shp", stringsAsFactors = FALSE) metro <- st_read(dsn = "C:/Users/Xo/Desktop/GeoDATA/metroParis.shp", stringsAsFactors = FALSE) IRIS <- st_read(dsn = "C:/Users/Xo/Desktop/GeoDATA/iris.shp", stringsAsFactors = FALSE) velos <- st_read(dsn = "C:/Users/Xo/Desktop/GeoDATA/reseau-cyclable.shp", stringsAsFactors = FALSE) toilettes <- st_read(dsn = "C:/Users/Xo/Desktop/GeoDATA/sanisettesparis.shp", stringsAsFactors = FALSE) ``` ___ ## Visualiser les arrondissements De base toute les variables sont cartographiées ``` plot(ardt) ``` ![](https://i.imgur.com/4mwyJN7.png) Plot en fonction d'une variable ``` plot(ardt["l_ar"]) ``` ![](https://i.imgur.com/lJbeofA.png) ## Visualiser les IRIS Cartographier les IRIS en fonction de l'arrondissement ``` plot(IRIS["nom_com"]) ``` ![](https://i.imgur.com/ABU5ZNR.png) ___ ## Ecrire un shapefile ``` st_write(ardt, "C:/Users/Xo/Desktop/GeoDATA/arrondissements2.shp") ``` ## Ecrire un geopackage avec plusieurs couches ``` st_write(metro, "C:/Users/Xo/Desktop/metro.gpkg", "metro", append= TRUE) st_write(ardt, "C:/Users/Xo/Desktop/metro.gpkg", "ardt", append= TRUE) ``` ___ ## Voir le SCR d'une couche ``` st_crs(ardt) ``` ![](https://i.imgur.com/E4V4gva.png) ___ ## Reprojeter une couche ``` ardt2154<- st_transform(ardt, 2154) ``` ___ ## Géoférencer un CSV **Géoréférencer le csv des arbres** * Importer le csv des arbres * Créer les deux colonnes lat/long * Tranformer le en objet SF * Cartographier les arbres en fonction de l'arrondissement ``` Arbres <- Arbres %>% separate(col= geo_point_2d, into = c("Latitude", "Longitude"), sep= ",") arbresgeo = st_as_sf(arbres, coords=c("Longitude","Latitude"), crs=4326) plot(arbresgeo["ARRONDISSEMENT"]) ``` ![](https://i.imgur.com/sW02jxw.png) **Géoréférencer le csv des emplacements de stationnement de vélos** ![](https://i.imgur.com/xsgkbew.png) ## Jointure attributaire * Importer le fichier csv ParisINSEE * Faire la jointure * cartographier la variable de médiane du niveau de vie (MNV) ``` ArdtINSEE <- merge(ardt2154, ParisINSEE, by.x = c("c_arinsee"), by.y = c("CodeArdt")) ``` ![](https://i.imgur.com/OSjboWw.png) * Pour changer la discrétisation il suffit d'ajouter un paramètre "breaks" * Pour changer la position de la légende il suffit d'ajouter un paramètre dans la commande (1=below, 2=left, 3=above and 4=right) ``` plot(ArdtINSEE["MNV"], breaks = "quantile", key.pos = 1) ``` ![](https://i.imgur.com/E2uukic.png) ## Centroides Afficher les centroïdes des IRIS ``` plot(st_centroid(IRIS["iris"])) ``` Créer une couche des centroïdes des IRIS ``` centroIRIS <- st_centroid(IRIS) ``` --- ## Operateurs topographiques ### Calcul d'aire Ajouter à la couche des arrondissements une colonne surface ``` ardtok <- ardtok %>% mutate(surface2 = st_area(ardtok)) ``` Calculer et cartographier les surfaces des IRIS ``` IRIS <- IRIS %>% mutate(surface = st_area(IRIS)) plot(IRIS["surface"]) ``` ___ ### Calcul de perimètre ``` install.packages("lwgeom") library(lwgeom) ``` Ajouter à la couche arrondissement une colonne périmètre ``` ardtok <- ardtok %>% mutate(longueur2 = st_perimeter(ardtok)) ``` ___ ### Calcul de longueur Cartographier la couche vélos en fonction du statut des tronçons ![](https://i.imgur.com/wOQqwk7.png) Ajouter à la couche vélo une colonne longueur N'oublier pas de reprojeter cette couche en 2154 ! ``` velos <- st_transform(velos, 2154) velos <- velos %>% mutate(longueur = st_length(velos)) ``` Cartographier la nouvelle variable en utilisant les quantiles ``` plot(velos["longueur"], breaks = "quantile", key.pos = 1) ``` ![](https://i.imgur.com/qfAVYGE.png) ___ ### Faire un **buffer** Faire un buffer de 200m autour des stations de métro ``` Buffermetro <- st_buffer(metro, dist=200) plot(Buffermetro["ligne"]) ``` ![](https://i.imgur.com/DWau8yN.png) Regrouper les buffers ``` Buffermetro <-st_union(Buffermetro) ``` ![](https://i.imgur.com/DxOEWF1.png) Faire une zone d'influence de 300m autour des toilettes publiques ![](https://i.imgur.com/Qsj1MxV.png) ___ ### Dissolve Regrouper les IRIS par arrondissement ``` ARDT <- IRIS %>% group_by(insee_com) %>% summarise() ``` ___ ### Dissolve with stat Regrouper les IRIS par arrondissement avec un résumé statistique de la surface (somme) ``` ARDT <- IRIS %>% group_by(insee_com) %>% summarise(NbIris = n(), Surface = sum(surface)) ``` --- ## Jointure spatiale **Ajouter à chaque station de métro le nom de l'arrondissement** ``` spatialjoin <- st_join(metro, ardt2154["l_ar"]) plot(spatialjoin["l_ar"]) ``` ![](https://i.imgur.com/EBBfr0U.png) **Ajouter à chaque arbres le nom de l'IRIS** ![](https://i.imgur.com/Yixu37U.png) ## Compter le nombre de point dans un polygone **Compter le nombre de metro par IRIS** ``` IRIS <- IRIS %>% mutate(nbMetro = lengths(st_intersects(IRIS, metro))) ``` **Compter le nombre d'arbres par IRIS** ``` IRIS <- IRIS %>% mutate(nbarbres = lengths(st_intersects(IRIS, arbresgeo))) ``` **Compter à la fois le nombre de toilettes et de stations de métro dans chaque Arrondissement** ``` Ardt <- Ardt %>% mutate(nbMetro = lengths(st_intersects(Ardt, metro)), nbtoilettes = lengths(st_intersects(Ardt, WC))) ``` ![](https://i.imgur.com/EfG4PiT.png) **Compter pour chaque IRIS le nombre de stations de métros, le nombre d'arbres, le nombre de toilettes et le nombre de stationnements de vélos** ![](https://i.imgur.com/vBDj5Zs.png) **Garder uniquemebt les IRIS contenant :** * plus de 2 stations de métro * plus de 500 arbres * plus de 3 emplacements de vélos ![](https://i.imgur.com/GPpz6hw.png) ## Jointure spatiale avec résumé statistique (somme) **Calculer la somme totale des transactions DVF 2017 par arrondissement** ``` SumDVFARDT <- ardt2154 %>% st_join(DVF) %>% group_by(l_ar) %>% summarise( total = sum(prix)) ``` **Calculer les longueurs de piste cyclables par IRIS** ``` IRISvelo <- IRIS %>% st_join(velos) %>% group_by(nom_iris) %>% summarise( longueurvelo = sum(longueur)) plot(IRISvelo["longueurvelo"], breaks = "quantile", key.pos = 1) ``` ![](https://i.imgur.com/ogJJ8W4.png) ## Jointure spatiale avec résumé statistique (moyenne) **Calculer la moyenne des prix au m² par IRIS et faite une carte** ``` M2moyenIRIS <- IRIS %>% st_join(DVF) %>% group_by(nom_iris) %>% summarise( prixm2moyen = mean(M2OK)) ``` ![](https://i.imgur.com/RIVc4ny.png) **Calculer la surface moyenne des biens par IRIS et cartographier cette nouvelle variable** ![](https://i.imgur.com/vQZdE30.png) ___ ## Calculer un ensemble de statistiques issues de l'agrégation ``` DVFardt <- ardt2154 %>% st_join(DVF) %>% group_by(l_ar) %>% summarise( nb = n(), total = sum(prix), prixmoyen = mean(prix), prixm2 = mean(M2OK) ) ``` ___ ## Créer une grille **Créer une grille de type hexagonale de 500m** ``` grille <- st_make_grid( ardt2154, cellsize = 500, crs = 2154, what = "polygons", square = FALSE) ``` ![](https://i.imgur.com/dlrkAZm.png) Pour changer la forme agir sur le paramètre `square` True ou False ``` grille2 <- st_make_grid( ardt2154, cellsize = 500, crs = 2154, what = "polygons", square = TRUE) ``` ![](https://i.imgur.com/GPnw0lc.png) **Compter le nombre d'arbres dans la grille hexagonale** ``` grille <- st_sf(grille) grille <- grille %>% mutate(nbarbres = lengths(st_intersects(grille, arbresgeo))) ``` ![](https://i.imgur.com/skRogl2.png) **Compter le nombre de transactions DVF dans la grille hexagonale** ![](https://i.imgur.com/MjE0z2u.png) **Calculer le prix moyen au m² dans le carroyage hexagonale** Il faut d'abor créer un champ de regroupement comme une ID puis procéder à l'agrégation spatiale avec résumé statistique ``` grille <- grille %>% mutate(id = row_number()) grille <- grille %>% mutate(IDOK = id) grillem2 <- grille %>% st_join(DVF) %>% group_by(IDOK) %>% summarise( prixm2moyen = mean(M2OK)) plot(grillem2["prixm2moyen"], breaks = "quantile", key.pos = 1) ``` ![](https://i.imgur.com/YuCWP3O.png) **Mettre en place un petit script qui :** * Crée la grille à la volée * Fait l'agrégation du prix moyen au m² * Sort une carte ``` grille300 <- st_make_grid( ardt2154, cellsize = 300, crs = 2154, what = "polygons", square = TRUE) grille <- st_sf(grille300) grille <- grille %>% mutate(id = row_number()) grille <- grille %>% mutate(IDOK = id) grillem2 <- grille %>% st_join(DVF) %>% group_by(IDOK) %>% summarise( prixm2moyen = mean(M2OK)) plot(grillem2["prixm2moyen"], breaks = "quantile", key.pos = 1) ``` ![](https://i.imgur.com/Rz97CqU.png) ## Intersection **Ne garder que les stations de métro du 1er arrondissement** ``` Premierardt <- ardt2154 %>% filter(c_arinsee == 75101) metro1er <- st_intersection(metro, Premierardt) ``` **Ne garder que les arbres du 16eme arrondissement** ``` Seizerardt <- ardt2154 %>% filter(c_arinsee == 75116) arbres16eme <- st_intersection(arbresgeo, Seizerardt) ``` ![](https://i.imgur.com/Vx3t5Ll.png) **Produire une couche avec tous les transactions DVF situés à moins de 100m d'une station de métro** ``` Buffermetro <- st_buffer(metro, dist=100) DVFmetro <- st_intersection(DVF, Buffermetro) ``` ![](https://i.imgur.com/DY2Gtzq.png) **Garder tous les arrêts de métro situés à moins de 100m d'une piste cyclable** ``` pistecyclables <- velos %>% filter(typologie_s == 'Bandes cyclables') metroprevelos <- st_intersection(metro, st_buffer(pistecyclables, 100)) %>% distinct(id_ref_zdl) ``` **Produire une couche avec tous les arbres situés à moins de 200m d'un métro et 100m d'un toilette publique** ``` Buffermetro <- st_buffer(metro, dist=200) BufferWC <- st_buffer(WC, dist=100) buffer <- st_intersection(Buffermetro,BufferWC) Arbresendanger <- st_intersection(arbresgeo, buffer) ``` ![](https://i.imgur.com/h5wrrrO.png) **Garder tous les toilettes situés à moins de 100m d'une piste cyclable et à moins de 100m d'un métro** **Produire une couche avec toutes les transaction DVF situées à moins de 300m d'un métro, à plus de 100m d'un toilette publique et à moins de 100m d'une piste cyclable** ``` Buffermetro <- st_buffer(metro, dist=300) Buffervelo <- st_buffer(velos, dist=100) BufferWC <- st_buffer(WC, dist=100) BufferWC <- st_union(BufferWC) Inclusion <- st_intersection(Buffermetro,Buffervelo) Inclusion <- st_union(Inclusion) Exclusion <- st_difference(Inclusion, BufferWC) DVFOK <- st_intersection(DVF, Exclusion) ``` ## Trouver l'entité la plus proche ## Jouer avec les Trips ### Importer le dataset ``` tracesoiseaux <- st_read(dsn = "D:/Cours/13-Automne2020/DataViz_Cergy/Data_KeplerGL/9_Traces_Oiseaux.geojson") ``` ### Transformer l'objet SF en dataframe ``` tracesoiseaux <- as.data.frame(tracesoiseaux) ``` ### Changer le timestamp en temps POSIX ``` tracesoiseaux$timestamp <- as_datetime(tracesoiseaux$timestamp) tracesoiseaux <- tracesoiseaux %>% mutate(UNIX= as.numeric(as.POSIXct(timestamp))) ``` ### Créer une colone altitude (si elle n'existe pas) ``` tracesoiseaux<- tracesoiseaux %>% mutate(altitude = 10) ``` ### Concaténer la colonne altitude et de temps dans une seule colonne avec un séparateur facile à transformer par la suite ``` tracesoiseaux <- tracesoiseaux %>% mutate(other=paste(altitude, UNIX, sep='12345')) ``` ### Créer le Geojson (sous forme de ligne) avec la structuration attendue ``` Tripsoiseaux <- tracesoiseaux %>% st_as_sf(coords = c("long", "lat", "other")) %>% group_by(tag_ident) %>% summarise(do_union = FALSE) %>% st_cast("LINESTRING") ``` ### Ecrire le GeoJson ``` st_write(Tripsoiseaux, "tripoiseaux.geojson", append = TRUE) ``` ### Remplacer dans le GeoJson le séparateur bidon (12345) par une ,