-
Notifications
You must be signed in to change notification settings - Fork 1
/
arbresosmdoc.Rmd
executable file
·244 lines (178 loc) · 8.77 KB
/
arbresosmdoc.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
---
title: "Les arbres isolés dans Open Street Map"
author: "Olivier Leroy"
date: "24 octobre 2018"
output: pdf_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
### DB
library(RPostgreSQL) # fait le lien avec postgre, utilise DBI
### manip
library(dplyr) # manip de données en tidyverse
library(tibble)
library(lubridate)
### visualisation
library(ggplot2) # la visualisation
library(tmap) # carto
## analyse spatiale / carto
library(sp) # classes et methodes pour données spatiales pe déclassé par SF
library(rgdal) #gdal pour projection, crud et surtout export
library(rgeos) # geos, penser à installer libgeos++-dev avant, travail avec objet sp
library(sf) # nouveau package de classes et methodes spatiales doit "remplacer" rgdal et rgeos (et ofc sp)
library(units) # gestion des unités pour ha
```
# Jeux de données
Les données sont issues d'un import d'OSM via <https://www.geofabrik.de/>. L'import c'est fait dans une BD Postgresql (10) avec les extensions postgis, postgis_topology et hstore. Pour avoir les noms des contributeurs et la date il faut s'identifier sur le site.
NB : modif novembre on a pris la source de datagouv
## Création de la BD
La base à d'abord été crée : en psql, et connecté en postgres (sudo -i -u postgres)
```{sql, eval = FALSE}
CREATE DATABASE [sonpetitnom];
CREATE EXTENSION postgis;
CREATE EXTENSION postgis_topology;
CREATE EXTENSION hstore;
```
## import/peuplement de la BD
Puis importée via [osm2pgsql](https://wiki.openstreetmap.org/wiki/Osm2pgsql)
```{bash, , eval = FALSE}
sudo -u postgres osm2pgsql -d [sonpetitnom]--slim --cache 10000 --number-processes 2 --hstore -x --multi-geometry /home/lo82302h/Téléchargements/france-latest.osm.bz2 -W
```
-d indique la DB osmdbfrance \hfill\break
- -slim permet de sauver les données temporaires dans la DB plutot que dans la RAM \hfill\break
- -hstore indique qu'il y un type de données hstore (spécifique à postgreSQL) \hfill\break
- -x ajoute les infos extras comme le contributeurs \hfill\break
-C --cache indique la RAM à utilisée \hfill\break
- -multi-geometry va créer des geometries multiples plutôt que de séparer en simple \hfill\break
-W demande le code ici de postgres \hfill\break
# Analyse exploratoire
## stats de base
Au moment de l'import (mi-otobre) il y avait 828488 lignes correspondant à des arbres isolés (natural=tree). Ils étaient renseignés par 29 champs (en plus de 'tags' et 'natural') completés par 162 champs dans tags. Cela ne fait donc rien que pour les arbres isolés 191 champs.
Species est le champs le plus renseigné : 99032 valeurs non nulles, soit près de 12%.
```{r, include=FALSE}
pw <- {
"mon_pwd" # oui c'est pas top de l'ecrire
}
# charge les drivers pour postgre
drv <- dbDriver("PostgreSQL")
# class(drv) #une verif
# fais un pont vers la db réutilisable
# ici j'ai pris une db en local pour tester
# con sera utilisé pour chaque connection et pkoi le franciser
con <- dbConnect(drv, dbname = "osmgouv",
host = "localhost", port = 5432, # attention 5432 par défaut
user = "postgres", password = pw) # idem pour user
rm(pw) # mouais
arbretemp_tags <- dbGetQuery(con, "SELECT * FROM arbres_osm_point;")
dim(arbretemp_tags)
names(arbretemp_tags)
querychamps <- "SELECT *
FROM planet_osm_point
WHERE planet_osm_point.natural = 'tree';"
nom_champs <- dbGetQuery(con, querychamps)
names_champs <- nom_champs %>% # on prends le total
summarise_all(funs(sum(!is.na(.)))) # on compte ceux renseignés
arbretemp <- nom_champs[,names_champs > 0] # on ne garde que les champs renseignés
# on groupe les deux tables
arbres_osm <- full_join(arbretemp, arbretemp_tags, by = "osm_id") #ici un bind_col pourrair aussi marcher
names_champs <- arbres_osm %>%
summarise_all(funs(sum(!is.na(.)))) %>%
t()
names_champs <- rownames_to_column(as.data.frame(names_champs), var = "champs") # on passe les noms de champs dans une variable
names_champs <- names_champs %>%
arrange(desc(V1)) # on range par ordre decroissant
names_champs <- names_champs[-c(1:4),] # on retire les valeurs toujours présentent
```
```{r}
names_champs[1:30,] %>%
ggplot( aes(x = reorder(champs, V1), y = V1)) +
geom_bar(stat = "identity") +
coord_flip()+
ylab("Nombres d'arbres") +
xlab("Champs")
```
### Répartition du champ "species"
On a une répartition très urbaine des arbres isolés réferencés dans OSM. Difficile à dire si il y a une logique sur ceux possedant une information de type "espèce", il semble cependant qu'il y ait des "clusters"
```{r, include=FALSE}
france.shp <- st_read(con, query = "SELECT name, way
FROM planet_osm_polygon
WHERE boundary = 'administrative' AND admin_level = '4';")
france.shp$surface_ha <- set_units(st_area(france.shp), value = ha) # on calcul la surface en ha
# on filtre par la surface pour enlever les paradis fiscaux
# on a encore un problème avc des îles italiennes aux larges de la corse, on vire Toscanna
# les objets units doivent être filtrés ou indexés par d'autre objets units d'ou le set_units(x, value = ha)
# pas certains que dplyr aime du coup c'est du r:base
plot(france.shp[france.shp$name != "Genève" & france.shp$surface_ha > set_units(30000, value = ha),])
france.shp <- france.shp[france.shp$name != "Genève" & france.shp$surface_ha > set_units(30000, value = ha),]
species.shp <- st_read(con, query = "SELECT way, tags -> 'species' AS species
FROM planet_osm_point
WHERE planet_osm_point.natural = 'tree';")
species.shp$especes <- factor(ifelse(is.na(species.shp$species), 0, 1))
```
```{r, fig.align= "center"}
tm_shape(st_simplify(st_geometry(france.shp)), dTolerance = 100) + # attention il a un simplify pour aller plus vite
tm_borders("grey") +
tm_shape(species.shp) +
tm_dots(alpha = 0.4, col = "especes", palette = c("#8be0b3", "red"))
```
Il y a 1846 valeurs différentes. Le wiki indique que "species" doit correspondre au nom latin (binomial).
On trouve plusieurs écart à cette règle :
* Les cas d'une information plus précise : le cultivar ou la variété de mentionné (avec plusieurs syntaxes possibles)
* Les cas de nomenclatures différentes : première lettre du descripteur
* Les erreurs :
+ Des plantes non ligneuses " iris versicolor" par exemple.
+ Uniquement le nom du genre : "platanus" / "Platanus"
+ Des noms vernaculaires, dans des langues variées : "Olivette blanche"
+ Des choses étranges : "OEIL"
+ etc...
#### Prenons le cas des platanes
Pour savoir où en sont les botanistes j'ai utilisé [TRNS](http://tnrs.iplantcollaborative.org/)
```{r}
#on enléve la geométrie
species.dat <- st_set_geometry(species.shp, value = NULL)
# un premier grep pour se rapprocher
temp <- unique(species.dat$species)[grep(pattern = "atan", unique(species.dat$species))]
# on enleve les érables, tillieul et robinier
paste("on obtient", length(temp[grep(pattern = "^A|T|R", temp, invert = T)]), "descripteurs pour platanes")
```
```{r}
species.dat %>%
filter(species %in% temp[grep(pattern = "^A|T|R", temp, invert = T)]) %>%
group_by(species) %>%
summarize(comptage = n()) %>%
arrange(desc(comptage)) %>%
print(n = Inf)
```
Ces 33 descripteurs couvrent 15415 arbres. Avant de regarder la botanique en detail il y a plusieurs problèmes.
##### Les noms de genre :
Le nom de genre devrait être mis dans l'attribut Key:genus. Selon le wiki osm pour ce dernier il doit être en latin et capitalisé. On retrouve dans cette categorie : platanus, Platanus, platane, platanes, Platanus sp ou encore Platanus n. sp.
##### les fautes de frappes
Elles sont des plusieurs types:
* Il y a l'absence de capitalisation du genre, la capitalisation du nom d'espèce et celle du croisememt (moins tranché)
* La coquille : Platanus aceriofolia
##### Les debats botaniques
Il y aussi les noms latins non tranchés chez les botanistes, les problèmes avec les croissements, les cultivars et variétés mis au niveau de l'espéce, etc.
### Utilisateurs et source de données
```{r}
# import des conributeurs et du moment de la contribution
user.dat <- dbGetQuery(con, "SELECT tags -> 'osm_timestamp' AS ts, tags -> 'osm_user' AS user
FROM planet_osm_point
WHERE planet_osm_point.natural = 'tree';")
user.dat$ts <- as_date(user.dat$ts) # on passe en POSIX juste date
# j'ai pris la 15aine mais on est presque de l'ordre du jour
ggplot(user.dat, aes(x = ts)) +
geom_histogram(binwidth = 15) +
xlab("Années") +
ylab("Nb. arbres isolés")
```
On a 2657 osm_users qui ont rentrés des arbres.
#### les arbres de reveries et d'OSM
```{r}
esp <- read.csv("nomsp_nomverma.csv", sep = "\t") # lecture du fichier
species.dat %>%
filter(species %in% esp$Species) %>%
group_by(species) %>%
summarize(comptage = n()) %>%
arrange(desc(comptage)) %>%
print(n = Inf)
```