-
Notifications
You must be signed in to change notification settings - Fork 0
/
arbres_stras.py
155 lines (128 loc) · 6.63 KB
/
arbres_stras.py
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
# coding: utf-8
from io import BytesIO
import folium
from folium.features import DivIcon
import geopandas as gpd
from IPython.display import display
import os
import pandas as pd
from urllib.request import urlopen
from zipfile import ZipFile
def download_unzip(zipurl, destination):
"""Download zipfile from URL and extract it to destination"""
print(f"On télécharge et on extraie {zipurl}...")
with urlopen(zipurl) as zipresp:
with ZipFile(BytesIO(zipresp.read())) as zfile:
zfile.extractall(destination)
class ArbreStras:
URL_PREFIX = "https://www.strasbourg.eu/documents/976405/"
STRASBOURG_COORD = (48.58, 7.75)
ARBRES_ZIP = URL_PREFIX + "1168331/CUS_CUS_DEPN_ARBR.zip"
ARBRES_CSV = "arbres/CUS_CUS_DEPN_ARBR.csv"
QUARTIERS_ZIP = URL_PREFIX + "1168339/CUS_CUS_DUAH_QUART.zip"
QUARTIERS_SHP = "quartiers/SHP/Quartiers_Strasbourg_15.shp"
def __init__(self, force_download=False):
"""On crée les data et la carte"""
self.force_download = force_download
self._load_arbres()
self._load_quartiers()
def _load_arbres(self):
if self.force_download or not os.path.isfile(self.ARBRES_CSV):
download_unzip(self.ARBRES_ZIP, "arbres")
arbres_all = pd.read_csv(self.ARBRES_CSV,
encoding='latin', # Pour prendre en compte l'encoding qui n'est pas utf-8
delimiter=";", # Le caractère séparateur des colonnes
decimal=',') # Pour convertir les décimaux utilisant la notation ,
self.arbres = arbres_all[arbres_all['point vert VILLE'] == "STRASBOURG"]
self.arbres = self.arbres.dropna(axis=0, how='any')
self.essences = set(self.arbres['Libellé_Essence'])
self.genre = set([essence.split()[0] for essence in self.essences])
# On construit le dico {genre: essence1, essence2, etc.}
self.essences_dict = {}
for essence in self.essences:
essence_splitted = essence.split()
genre = essence_splitted[0]
espece = ' '.join(essence_splitted[1:])
try:
especes = self.essences_dict[genre]
especes.append(espece)
except KeyError:
especes = [espece]
self.essences_dict.update({genre: especes})
def _load_quartiers(self):
if self.force_download or not os.path.isfile(self.QUARTIERS_SHP):
download_unzip(self.QUARTIERS_ZIP, "quartiers")
self.quartiers = gpd.read_file(self.QUARTIERS_SHP)
self.quartiers["QUARTIER"] = self.quartiers["QUARTIER"].str.lower()
self.quartiers["QUARTIER"] = self.quartiers["QUARTIER"].str.replace('_', ' ')
convertion_dict = {"CENTRE": "centre ville",
("BOURSE", "ESPLANADE", "KRUTENAU"): "bourse esplanade krutenau",
("ORANGERIE", "CONSEIL-XV"): "orangerie conseil des xv",
("GARE", "TRIBUNAL"): "gare tribunal",
("HAUTEPIERRE", "POTERIE"): "hautepierre poteries",
"MUSAU": "NEUDORF",
"STOCKFELD": "NEUHOF2",
"PLAINE DES BOUCHERS": "MEINAU",
"POLYGONE": "NEUHOF",
"PORTE DE SCHIRMECK": "ELSAU",
("ROBERTSAU", "WACKEN"): "ROBERTSAU WACKEN"}
for k, v in convertion_dict.items():
self.arbres['Point vert Quartier usuel'] = self.arbres['Point vert Quartier usuel'].replace(to_replace=k,
value=v)
self.arbres['Point vert Quartier usuel'] = self.arbres['Point vert Quartier usuel'].str.lower()
self.quartiers['coords'] = self.quartiers['geometry'].to_crs(epsg='4326').apply(lambda x: x.centroid.coords[:])
self.quartiers['coords'] = [coords[0] for coords in self.quartiers['coords']]
def _create_map(self, data, legende):
# On crée une carte initialement centrée sur Strasbourg
fmap = folium.Map(self.STRASBOURG_COORD, zoom_start=11, tiles='cartodbpositron')
# On ajoute les données des quartiers
folium.GeoJson(self.quartiers).add_to(fmap)
folium.Choropleth(geo_data=self.quartiers,
data=data,
key_on='feature.properties.QUARTIER',
fill_color='YlGn',
fill_opacity=0.5,
line_opacity=0.2,
legend_name=legende).add_to(fmap)
for idx, row in self.quartiers.iterrows():
nom = '<br>'.join(row["QUARTIER"].title().split())
html_div = f'<div style="font-size: 7pt">{nom}</div>'
folium.map.Marker((row['coords'][1], row['coords'][0]),
icon=DivIcon(icon_size=(150, 36),
icon_anchor=(0, 0),
html=html_div)
).add_to(fmap)
display(fmap)
def plot(self, essence="tous", representation="densité"):
"""Trace la représentation géographique par quartier"""
if essence == 'tous':
libelle = ''
df = self.arbres
ds = self.arbres['Point vert Quartier usuel']
else:
libelle = "de " + essence.replace(r"'", r"\'")
df = self.arbres[self.arbres['Libellé_Essence'] == essence]
ds = df['Point vert Quartier usuel']
hauteurs = df.groupby(['Point vert Quartier usuel'])['Hauteur arbre']
if representation == "densité":
data_count = ds.value_counts()
aires = self.quartiers.area
aires.index = self.quartiers["QUARTIER"]
ds_plot = data_count / aires * 10000
legende = r"Nombre {} par hectare".format(libelle)
elif representation == "nombre":
ds_plot = ds.value_counts()
legende = "Nombre " + libelle
elif representation == "hauteur moyenne":
ds_plot = hauteurs.mean()
legende = "Hauteur moyenne [m] " + libelle
else:
raise Exception(f"représentation inconnue: {representation}")
ds_plot = ds_plot.fillna(0)
self._create_map(ds_plot, legende)
if __name__ == '__main__':
stras_arbres = ArbreStras()
stras_arbres.plot()
stras_arbres.plot(essence="tous", representation="nombre")
stras_arbres.plot(essence='Abies grandis')
stras_arbres.plot(essence='Abies grandis', representation="densité")