User:Defuneste/Les alignements d'arbres de Lyon Métropole

From OpenStreetMap Wiki
Jump to: navigation, search

Cette page a pour vocation de présenter :

  1. les alignements d'arbres de Lyon Métropole ;
  2. les opérations effectuées pour préparer l'import ;
  3. les imports effectués.

Les alignements d'arbres de Lyon Métropole

Les données ont été téléchargées, le 8 janvier 2019, sur le site Data Grand Lyon à cette adresse. Elles ont été téléchargées sous format shape(.shp) (les autres formats ne semblaient pas accessibles) avec l'EPSG 4326 comme système de projection.

Les opérations effectuées pour préparer l'import

L'exploration et le "nettoyage" des données est fait sur R avec en package : sp, sf, dplyr et ggplot2 (il est possible de publier les scripts au besoin). C'est un fichier shape de points qui regroupe 94435 arbres caractérisés par 25 champs. Je me suis concentré sur les champs indiqués comme souhaitable dans le wiki.


Genre / Key:genus et Espèce / Key:species

Genre

La variable genre comprend trois valeurs étranges :

  • "Emplacement libre" : 3447 lignes
  • "souche" : 1615 lignes
  • "Non défini" : 12 lignes

"Emplacement libre" comprend une très grande majorité de valeurs nulles (0) qui devraient être considérées comme NA et quelques valeurs positives (une absence d'arbre avec une hauteur) qui sont probablement des artefacts. Cela semble correspondre à des endroits où des arbres peuvent être plantés mais ne le sont pas encore. "Souche" doit correspondre à des arbres morts. Seul deux d'entre eux ont une circonférence et trois une hauteur. Je ne pense pas que cela soit important. "Non défini" est étrange car tous possèdent une circonférence, il est donc possible que cela soit des arbres non identifiés mais qui existent bien.

Dans le cadre d'OSM je pense qu'il ne faut pas garder ces lignes ("on cartographie le terrain"). Il faut ensuite renommer la variable en genus

arbres_lyon.shp$filtre <- 0
arbres_lyon.shp$filtre[arbres_lyon.shp$genre == "Emplacement libre"] <- 1
arbres_lyon.shp$filtre[arbres_lyon.shp$genre == "souche"] <- 1
arbres_lyon.shp$filtre[arbres_lyon.shp$genre == "Souche"] <- 1
arbres_lyon.shp$filtre[arbres_lyon.shp$genre == "Non défini"] <- 1
arbres_lyon.shp <-arbres_lyon.shp %>% filter(filtre == 0)

Il y a également deux valeurs manquantes (NA) pour genre. Ce sont deux Hibiscus.

arbres_lyon.shp[is.na(arbres_lyon.shp$genre),] # ici on vérifie les NA
#genre est un facteur, je le garde comme tel mais on pourrait aussi s'en passer
levels(arbres_lyon.shp$genre) <- c(levels(arbres_lyon.shp$genre), "Hibiscus")
arbres_lyon.shp$genre[is.na(arbres_lyon.shp$genre)] <- "Hibiscus"

Espèce

Espèce ne comprend presque que des noms latins uniques (campestre par ex). On aurait pu attendre qu'elle corresponde comme dans OSM au nom latin de l'espèce (Acer campestre). En plus, cette variable comprend trois termes posant questions :

  • "hybride" : 2148 lignes
  • "hybride turneri" : 1 lignes
  • "x zoeschense" : 17 lignes

Il est possible que ces trois termes soient tous liés à la façon dont la base a codé les hybrides (et Espèce). Les hybrides sont un cas particulier du nom latin (constitué majoritairement de deux noms) constitué alors de trois mots. Ici le champs espèce est probablement une extraction automatique du second nom. L'extraction n'aurait prévue le cas des hybrides.


Utiliser "hybride" plutôt que × qui est un caractère particulier n'est pas une mauvaise idée et éviterait des tas de problèmes d'encodage (on utilise souvent x pour aller plus vite). Il semble cependant que × est plus rigoureux et valide dans toute les langues.

Voici les modifications :

arbres_lyon.shp$espece <- recode(arbres_lyon.shp$espece, hybride = "×" )
arbres_lyon.shp$variete[arbres_lyon.shp$espece == "hybride turneri"] <- "turneri"
arbres_lyon.shp$espece[arbres_lyon.shp$espece == "hybride turneri"] <- "×"
arbres_lyon.shp$variete[arbres_lyon.shp$espece == "x zoeschense"] <- "zoeschense"
arbres_lyon.shp$espece[arbres_lyon.shp$espece == "x zoeschense"] <- "×"
sort(unique(arbres_lyon.shp$espece)) #une verif pas indispensable


Et ici la composition d'un nom d'espèce pour les hybrides puis pour les arbres "normaux". Si paste comporte une valeur manquante il retourne NA ce qui me convient.

arbres_lyon.shp$species <- ifelse(arbres_lyon.shp$espece == "×" , 
paste(arbres_lyon.shp$genre, arbres_lyon.shp$espece, arbres_lyon.shp$variete), 
paste(arbres_lyon.shp$genre, arbres_lyon.shp$espece))


La circonférence : Key:circumference

La circonférence est difficile à visualiser (le diamètre est plus parlant), à titre d’exemple : un arbre de 1 m de DHP (diamètre à hauteur de poitrine) a une circonférence de 3,14 m et 2 m donne 6,28 m (ce sont de très gros arbres).

circonfere est le champs qui semble correspondre à la circonférence. OSM recommande l'usage du m et circonfere doit être plus en m. La mediane serait donc de 0,49 m et non pas 49 m soit 0.1559718 m de DHP.

summary(arbres_lyon.shp$circonfere)

Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
0.00 25.00 49.00 67.55 93.00 12210.00 9

La circonférence minimale de 0 concerne 8618 arbres. C’est, soit une absence de donnée mal codée (devrait être NA dans le cas des "emplacement libre" et "souche"), ou alors on est face à des arbustes qui n’ont pas encore de circonférence à 1,30. Est-ce possible ?

Si elle est bien en cm il est peu probable que l’on ait des arbres de plus de 628 cm de circonférence (des arbres de 2 m de DHP sont très rares).

table(arbres_lyon.shp$circonfere[arbres_lyon.shp$circonfere >= 628])

Circonférence (cm) 800 997 999 1069 1114 12210
Nb d'arbres 29 1 43 1 1 1

Le plus évident est l’arbre de 12210 cm de circonférence (prés de 39 m de rayon) qui doit correspondre à une erreur de frappe. Vient ensuite les "999" qui sont souvent utilisés pour indiquer des valeurs manquantes, le fait qu’ils aient tous été plantés après 2005 renforce cette idée. Les 29 arbres ayant une valeur 800 de circonfere ont tous été plantés le même jour (2018-06-25) et sont sur la même avenue (avenue Bataillon Carmognole Liberté, Vaulx-en-Velin). On peut éliminer l’hypothèse de gros arbres. S'ils ont tous le même diamètre et qu’ils ont bien été tous plantés la même date, il est possible que de jeunes arbres aient 0,08 m (8cm de circonférence). Dans un premier temps il me semble cependant plus sage de leur attribuer une valeur manquante. Pour les dernières valeurs (997, 1069 et 1114) il est probable que l’on soit aussi dans une erreur d’encodage et donc en attendant ils prendront également NA.

arbres_lyon.shp$circumference <- arbres_lyon.shp$circonfere/100 # passage en m
# gros arbres en NA
arbres_lyon.shp$circumference[arbres_lyon.shp$circumference >= 6.28] <- NA 
# valeurs nulles en NA
arbres_lyon.shp$circumference[arbres_lyon.shp$circumference == 0] <- NA


La hauteur Key:height

Je pense que c'est un des critères les plus difficiles à estimer et qui héberge souvent une proportion un peu plus forte de valeurs "rondes" (ici par exemple 30). Dans la base c'est hauteurtot qui correspond à la hauteur (hauteur totale). La hauteur de fût est également renseignée mais je ne pense pas que cela soit une bonne idée de la garder dans OSM.

Il y a 5047 arbres avec une hauteur nulle (`0`). Il est probable que ce 0 corresponde à des valeurs manquantes. Une partie correspond aux "Emplacement libre". L'unité semble bien être le m.

Il est très peu probable d'avoir des arbres de plus de 50 m (j'ai aussi des doutes pour ceux de plus de 40 m).

table(arbres_lyon.shp$hauteurtot[arbres_lyon.shp$hauteurtot >= 50])

50 61 64 66 67 90 2020
nb d'arbres 1 1 1 2 2 1 1


2020 est probablement une faute de frappes (20 et 20 ?). 50 m est une option possible (50 m c'est une piscine olympique et c'est presque impossible pour un feuillus, ici un platane). Les autres hauteurs sont donc aussi des erreurs.

arbres_lyon.shp$hauteurtot[arbres_lyon.shp$hauteurtot >= 50] <- NA
arbres_lyon.shp$hauteurtot[arbres_lyon.shp$hauteurtot == 0] <- NA


Rayon de la couronne : diameter_crown=*

rayoncouro correspond au rayon de la couronne du houppier. C'est un paramètre (diameter_crown=*) pas bien décrit dans le wiki OSM. Partons du principe que l'on a un rayon en m correspondant à un demi diamètre.

Il y a 5070 valeurs nulles. Il est préférable d'attribuer NA. Dans les valeurs extrêmes seulement 25 et 29 sortent du lot et devraient être passer comme NA.

arbres_lyon.shp$rayoncouro[arbres_lyon.shp$rayoncouro == 0] <- NA
arbres_lyon.shp$rayoncouro[arbres_lyon.shp$rayoncouro >= 25] <- NA


Dateplanta et anneeplant

summary(arbres_lyon.shp$dateplanta)
summary(arbres_lyon.shp$anneeplant)

Ce ne sont pas des critères présents dans le wiki. On les retrouve cependant relativement renseigné dans les arbres isolés de la métropole. Faut-il les garder ?

dateplanta correspond à des dates de plantation au format YYYY-MM-DD et anneeplant correspond à l'année. Ils correspondent bien, donc autant ne garder que le premier. Le format est celui de start_date:FR:plantation dans OSM.

Une rapide vérification indique des arbres plantés en 1616 et 1664 avec de petites diamètres. Les deux arbres plantés en 1861 et celui en 1894 ont de gros diamètres et sont plus crédibles. Beaucoup d'arbres plantés en 1900 sont douteux mais il serait nécessaire d'en savoir plus avant de leur attribuer NA. A l’opposé l'arbre planté en 2025 et celui en 2019 semblent être des fautes de frappes et vont devoir également prendre NA pour valeur.

arbres_lyon.shp$rayoncouro[arbres_lyon.shp$dateplanta <= 1850] <- NA
arbres_lyon.shp$rayoncouro[arbres_lyon.shp$dateplanta >= 2019] <- NA


Mise en forme pour OSM

Ici l'objectif est de mettre en forme et de ne garder que les variables utiles dans OSM.

leaf_type et Leaf_cycle

Un import du tableau du wiki des correspondances entre des genres, des types de feuillages et sa persistance.

leaf <- read.csv2("leaft_type.csv", sep = "\t")

On compare ce tableau avec la liste des genres de la base Lyonnaise :

sort(unique(arbres_lyon_final.shp$genus)[unique(arbres_lyon_final.shp$genus) %in% leaf$Genus]) # liste des genres présents
sort(unique(arbres_lyon_final.shp$genus)[!(unique(arbres_lyon_final.shp$genus) %in% leaf$Genus)]) # liste des genres absents

Seulement 23 genres sont présents. Vérifier ces genres avec Wikipédia (cf. tableau plus bas) permet de trouver trois orthographes de genres pouvant être corrigé : Pirus, Thuya et Evodia. Passer dans TNRS pour confirmer Pirus est bien Pyrus et Thuya est bien Thuja par contre les deux versions Evodia et Euodia sont possibles (je n'ai gardé qu'Euodia en suivant le wiki mais c'est discutable).

levels(arbres_lyon_final.shp$genus)[levels(arbres_lyon_final.shp$genus) == "Thuya"] <- "Thuja"
levels(arbres_lyon_final.shp$genus)[levels(arbres_lyon_final.shp$genus) == "Pirus"] <- "Pyrus"
levels(arbres_lyon_final.shp$genus)[levels(arbres_lyon_final.shp$genus) == "Evodia"] <- "Euodia"
Tableau des correspondances entre genre et types de feuillage (absent du wiki)
Genus leaf_cycle leaf_type
Acacia deciduous broadleaved
Acer deciduous and evergreen broadleaved
Aesculus deciduous broadleaved
Ailanthus deciduous broadleaved
Albizia deciduous broadleaved
Alnus deciduous broadleaved
Amelanchier deciduous broadleaved
Betula deciduous broadleaved
Broussonetia deciduous broadleaved
Buxus evergreen broadleaved
Carpinus deciduous broadleaved
Castanea deciduous broadleaved
Catalpa deciduous and evergreen broadleaved
Cedrela deciduous and evergreen broadleaved
Celtis deciduous broadleaved
Cercidiphyllum deciduous broadleaved
Cercis deciduous broadleaved
Chimonanthus deciduous and evergreen broadleaved
Cladrastis deciduous broadleaved
Cornus deciduous and evergreen broadleaved
Corylus deciduous broadleaved
Crataegus deciduous broadleaved
Davidia deciduous broadleaved
Diospyros deciduous broadleaved
Elaeagnus deciduous and evergreen broadleaved
Eucalyptus deciduous and evergreen broadleaved
Euodia deciduous broadleaved
Fagus deciduous broadleaved
Firmiana deciduous broadleaved
Fraxinus deciduous and evergreen broadleaved
Gleditsia deciduous broadleaved
Gymnocladus deciduous broadleaved
Hibiscus deciduous and evergreen broadleaved
Idesia deciduous broadleaved
Juglans deciduous broadleaved
Koelreuteria deciduous broadleaved
Lagerstroemia deciduous and evergreen broadleaved
Ligustrum deciduous and evergreen broadleaved
Liquidambar deciduous broadleaved
Liriodendron deciduous broadleaved
Maclura deciduous broadleaved
Magnolia deciduous and evergreen broadleaved
Malus deciduous broadleaved
Melia deciduous broadleaved
Mespilus deciduous broadleaved
Morus deciduous broadleaved
Nyssa deciduous broadleaved
Olea evergreen broadleaved
Ostrya deciduous broadleaved
Parrotia deciduous broadleaved
Paulownia deciduous broadleaved
Phellodendron deciduous broadleaved
Pyrus deciduous and evergreen broadleaved
Platanus deciduous broadleaved
Populus deciduous broadleaved
Prunus deciduous and evergreen broadleaved
Ptelea deciduous broadleaved
Pterocarya deciduous broadleaved
Rhus deciduous broadleaved
Robinia deciduous broadleaved
Salix deciduous broadleaved
Sambucus deciduous broadleaved
Sassafras deciduous broadleaved
Semiarundinaria deciduous broadleaved
Sophora deciduous broadleaved
Sorbus deciduous broadleaved
Syringa deciduous broadleaved
Ulmus deciduous broadleaved
Zelkova deciduous broadleaved
arbres_lyon_final.shp <- arbres_lyon.shp %>%
rename(genus = genre, ## ici on renome
"species:fr" = essencefra,
height = hauteurtot,
`start_date:FR:plantation` = dateplanta,
taxon = essence) %>%
mutate(diameter_crown = rayoncouro * 2,
"source:name" = "Arbres d'alignement de la métropole de Lyon",
"source:addr" = "https://data.grandlyon.com/") ## puis on supprime %>%
select(-hauteurfut, -diametreco, -rayoncouro, -circonfere, -anneeplant, -architectu, -localisati, -naturereve, -surfacecad,
-mobilierur, -commune, -codefuv, -nomvoie, -identifian, -numero, -codegenre, -filtre, -espece)
names(arbres_lyon_final.shp)

Une fois que l'on a un fichier avec une correspondance entre genus et leaf_type et leaf_cycle une jointure fait le travail.

# ouverture du fichier complémentaire
leaf2 <- read.csv2("leaf_type_ajout.csv", sep = "\t", stringsAsFactors = FALSE) 
leaf_tot <- rbind(leaf,leaf2) # rajout au fichier tiré du CSV
arbres_lyon_final.shp <- arbres_lyon_final.shp %>% # une jointure
left_join(leaf_tot, by = c("genus" = "Genus"))

Production de petits fichiers pour faire plusieurs imports

Il semble difficile de faire un gros import tout en contrôlant visuellement que l'on ne supprime pas des données terrain / d'utilisateurs ou n'ajoute pas de la données de mauvaise qualité. Diviser le travail en plusieurs fichiers semble une meilleur solution.

outlist <- list() # initialisation d'un liste
longueur <- length(unique(arbres_lyon_final.shp$codeinsee)) # le nombre de fichier souhaité
for(i in 1:longueur) {
# on passe par une liste, c'est pas indispensable mais je voulais vérifier un peu avant d'écrire des fichiers
outlist⟦i⟧ <- arbres_lyon_final.shp %>%
filter(codeinsee == unique(arbres_lyon_final.shp$codeinsee)[i])
# on écrit des tas de fichiers
st_write(outlist⟦i⟧, dsn = paste0(unique(arbres_lyon_final.shp$codeinsee)[i], ".geojson"))}

geojson semble bien passer avec JOSM, ce format présente l'avantage de prendre plus de 9 caractères dans le nom de variables et d’accepter les ":" souvent utilisés. Lors de ce travail la structure d'un tableau a été utilisée et mon export (la commande st_write) la reproduit dans les geojson. Cette méthode va utiliser plus d'espace que nécessaire : en absence d'information la clef est renseignée avec un "null". Il y a une amélioration possible mais je ne connais pas bien les outils pour le faire.


La suite est ici.

Voir aussi