
Analyse de données exploratoires géospatiales avec GeoPandas et DuckDB
Dans cet article, je vais vous montrer comment utiliser deux bibliothèques Python populaires pour effectuer une analyse géospatiale des données sur les accidents de la circulation au Royaume-Uni.
J’ai été un des premiers à adopter CanardDBla base de données rapide OLAP, après sa mise à disposition, mais n’a réalisé que récemment que, grâce à une extension, elle offrait un grand nombre de fonctions géospatiales potentiellement utiles.
Géopandas était nouveau pour moi. Il s’agit d’une bibliothèque Python qui donne l’impression de travailler avec des données géographiques comme avec des pandas ordinaires, mais avec une géométrie (points, lignes, polygones) intégrée. Vous pouvez lire/écrire des formats SIG standard (GeoJSON, Shapefile, GeoPackage), manipuler des attributs et des géométries ensemble et visualiser rapidement des couches avec Matplotlib.
Désireux de tester les capacités des deux, je me suis mis à rechercher un mini-projet utile qui serait à la fois intéressant et une expérience d’apprentissage utile.
Pour faire court, j’ai décidé d’essayer d’utiliser les deux bibliothèques pour déterminer la ville la plus sûre du Royaume-Uni pour conduire ou se promener. Il est possible que vous puissiez faire tout ce que je vais montrer en utilisant Geopandas seul, mais malheureusement, je ne le connais pas aussi bien qu’avec DuckDB, c’est pourquoi j’ai utilisé les deux.
Quelques règles de base.
Les données sur les accidents et les victimes que j’utiliserai proviennent d’une source officielle du gouvernement britannique qui couvre l’ensemble du pays. Cependant, je me concentrerai sur les données de seulement six des plus grandes villes du Royaume-Uni : Londres, Édimbourg, Cardiff, Glasgow, Birmingham et Manchester.
Ma méthode pour déterminer la ville « la plus sûre » consistera à calculer le nombre total de victimes de la route dans chaque ville sur une période de cinq ans et à diviser ce nombre par la superficie de chaque ville en km². Ce sera mon « indice de sécurité », et plus ce chiffre est bas, plus la ville est sûre.
Obtenir nos données sur les limites de la ville
C’était sans doute la partie la plus difficile de tout le processus.
Plutôt que de traiter une « ville » comme un polygone administratif unique, ce qui conduit à diverses anomalies en termes d’aires urbaines, j’ai modélisé chacune par ses zone bâtie (BUA) empreinte. Je l’ai fait en utilisant le Bureau des statistiques nationales (ONS) Zones bâties couche de données cartographiques, puis agrégé toutes les parties de la BUA qui se situent dans une limite administrative raisonnable pour cet emplacement. Le masque provient des limites officielles de l’ONS et est choisi pour refléter chaque zone urbaine plus large :
- Londres → le Région de Londres (Régions décembre 2023).
- Manchester → l’union des 10 Grand Manchester Districts d’autorité locale (LAD) pour mai 2024.
- Birmingham → l’union des 7 LAD de la West Midlands Combined Authority.
- Glasgow → l’union des 8 conseils de la région de la ville de Glasgow.
- Édimbourg et Cardiff → leur célibataire LAD.
Comment les polygones sont construits dans le code
J’ai téléchargé les données de limites directement depuis ArcGIS FeatureServer de l’Office britannique des statistiques nationales (ONS) dans GéoJSON format en utilisant la bibliothèque de requêtes. Pour chaque ville, nous construisons d’abord un masque à partir des couches d’administration officielles de l’ONS : le Région de London (décembre 2023) pour Londres ; le Union des Districts de Collectivité Locale (LAD, mai 2024) pour le Grand Manchester (10 LAD), le noyau des West Midlands (7 LAD) et la région de la ville de Glasgow (8 conseils) ; et le DAL simple pour Édimbourg et Cardiff.
Ensuite, j’interroge le Zones bâties de l’ONS (BUA 2022) calque pour les polygones coupant le cadre de délimitation du masque, en ne conservant que ceux qui se croisent le masque, et dissoudre (fusionner) les résultats pour créer un seul polygone en plusieurs parties par ville (« agrégat BUA 2022 »). Les données sont stockées et tracées dans EPSG:4326 (WGS84), c’est-à-dire que la latitude et la longitude sont exprimées en degrés. Lors du reporting des zones, nous les reprojetons au format EPSG : 27700 (OSGB) et calculons la superficie en kilomètres carrés pour éviter les distorsions.
Chaque donnée de limite de ville est téléchargée dans un fichier GeoJSON et chargée dans Python à l’aide des bibliothèques Geopandas et Requests.
Pour montrer que les données de limites dont nous disposons sont correctes, les couches de villes individuelles sont ensuite combinées dans un seul Geodataframe, reprojetées dans un système de référence de coordonnées cohérent (EPSG : 4326) et tracées au-dessus d’un plan propre. Aperçu du Royaume-Uni dérivé de l’ensemble de données Natural Earth (via un miroir GitHub). Pour nous concentrer uniquement sur le continent, nous recadrons le contour du Royaume-Uni jusqu’au cadre de délimitation des villes, à l’exclusion des territoires d’outre-mer éloignés. La superficie de chaque ville est également calculée.
Licence de données de frontière
Tous les ensembles de données de limites que j’ai utilisés sont données ouvertes avec des conditions de réutilisation permissives.
Londres, Édimbourg, Cardiff, Glasgow, Birmingham et Manchester
- Source : Office des statistiques nationales (ONS) — Comtés et autorités unitaires (mai 2023), UK BGC et Régions (décembre 2023) FR BGC.
- Licence: Licence du gouvernement ouvert v3.0 (OGL).
- Conditions : Vous êtes libre d’utiliser, de modifier et de partager les données (même commercialement) tant que vous en fournissez l’attribution.
Aperçu du Royaume-Uni
- Source : Terre naturelle —Administrateur 0 — Pays.
- Licence: Domaine public (aucune restriction).Citation:
- Terre naturelle.Administrateur 0 — Pays. Domaine public. Disponible à partir de : https://www.naturalearthdata.com
Code des limites de la ville
Voici le code Python que vous pouvez utiliser pour télécharger les fichiers de données de chaque ville et vérifier les limites sur une carte.
Avant d’exécuter le code principal, assurez-vous d’avoir installé les bibliothèques suivantes. Vous pouvez utiliser pépin ou une autre méthode de votre choix pour cela.
geopandas
matplotlib
requests
pandas
duckdb
jupyter
import requests, json
import geopandas as gpd
import pandas as pd
import matplotlib.pyplot as plt
# ---------- ONS endpoints ----------
LAD24_FS = "https://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/Local_Authority_Districts_May_2024_Boundaries_UK_BGC/FeatureServer/0/query"
REGION23_FS = "https://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/Regions_December_2023_Boundaries_EN_BGC/FeatureServer/0/query"
BUA_FS = "https://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/BUA_2022_GB/FeatureServer/0/query"
# ---------- Helpers ----------
def arcgis_geojson(url, params):
r = requests.get(url, params={**params, "f": "geojson"}, timeout=90)
r.raise_for_status()
return r.json()
def sql_quote(s: str) -> str:
return "'" + s.replace("'", "''") + "'"
def fetch_lads_by_names(names):
where = "LAD24NM IN ({})".format(",".join(sql_quote(n) for n in names))
data = arcgis_geojson(LAD24_FS, {
"where": where,
"outFields": "LAD24NM",
"returnGeometry": "true",
"outSR": "4326"
})
gdf = gpd.GeoDataFrame.from_features(data.get("features", []), crs="EPSG:4326")
if gdf.empty:
raise RuntimeError(f"No LADs found for: {names}")
return gdf
def fetch_lad_by_name(name):
return fetch_lads_by_names([name])
def fetch_region_by_name(name):
data = arcgis_geojson(REGION23_FS, {
"where": f"RGN23NM={sql_quote(name)}",
"outFields": "RGN23NM",
"returnGeometry": "true",
"outSR": "4326"
})
gdf = gpd.GeoDataFrame.from_features(data.get("features", []), crs="EPSG:4326")
if gdf.empty:
raise RuntimeError(f"No Region feature for: {name}")
return gdf
def fetch_buas_intersecting_bbox(minx, miny, maxx, maxy):
data = arcgis_geojson(BUA_FS, {
"where": "1=1",
"geometryType": "esriGeometryEnvelope",
"geometry": json.dumps({
"xmin": float(minx), "ymin": float(miny),
"xmax": float(maxx), "ymax": float(maxy),
"spatialReference": {"wkid": 4326}
}),
"inSR": "4326",
"spatialRel": "esriSpatialRelIntersects",
"outFields": "BUA22NM,BUA22CD,Shape__Area",
"returnGeometry": "true",
"outSR": "4326"
})
return gpd.GeoDataFrame.from_features(data.get("features", []), crs="EPSG:4326")
def aggregate_bua_by_mask(mask_gdf: gpd.GeoDataFrame, label: str) -> gpd.GeoDataFrame:
"""
Fetch BUA 2022 polygons intersecting a mask (LAD/Region union) and dissolve to one polygon.
Uses Shapely 2.x union_all() to build the mask geometry.
"""
# Union the mask polygon(s)
mask_union = mask_gdf.geometry.union_all()
# Fetch candidate BUAs via mask bbox, then filter by real intersection with the union
minx, miny, maxx, maxy = gpd.GeoSeries([mask_union], crs="EPSG:4326").total_bounds
buas = fetch_buas_intersecting_bbox(minx, miny, maxx, maxy)
if buas.empty:
raise RuntimeError(f"No BUAs intersecting bbox for {label}")
buas = buas[buas.intersects(mask_union)]
if buas.empty:
raise RuntimeError(f"No BUAs actually intersect mask for {label}")
dissolved = buas[["geometry"]].dissolve().reset_index(drop=True)
dissolved["city"] = label
return dissolved[["city", "geometry"]]
# ---------- Group definitions ----------
GM_10 = ["Manchester","Salford","Trafford","Stockport","Tameside",
"Oldham","Rochdale","Bury","Bolton","Wigan"]
WMCA_7 = ["Birmingham","Coventry","Dudley","Sandwell","Solihull","Walsall","Wolverhampton"]
GLASGOW_CR_8 = ["Glasgow City","East Dunbartonshire","West Dunbartonshire",
"East Renfrewshire","Renfrewshire","Inverclyde",
"North Lanarkshire","South Lanarkshire"]
EDINBURGH = "City of Edinburgh"
CARDIFF = "Cardiff"
# ---------- Build masks ----------
london_region = fetch_region_by_name("London") # Region mask for London
gm_lads = fetch_lads_by_names(GM_10) # Greater Manchester (10)
wmca_lads = fetch_lads_by_names(WMCA_7) # West Midlands (7)
gcr_lads = fetch_lads_by_names(GLASGOW_CR_8) # Glasgow City Region (8)
edi_lad = fetch_lad_by_name(EDINBURGH) # Single LAD
cdf_lad = fetch_lad_by_name(CARDIFF) # Single LAD
# ---------- Aggregate BUAs by each mask ----------
layers = []
london_bua = aggregate_bua_by_mask(london_region, "London (BUA 2022 aggregate)")
london_bua.to_file("london_bua_aggregate.geojson", driver="GeoJSON")
layers.append(london_bua)
man_bua = aggregate_bua_by_mask(gm_lads, "Manchester (BUA 2022 aggregate)")
man_bua.to_file("manchester_bua_aggregate.geojson", driver="GeoJSON")
layers.append(man_bua)
bham_bua = aggregate_bua_by_mask(wmca_lads, "Birmingham (BUA 2022 aggregate)")
bham_bua.to_file("birmingham_bua_aggregate.geojson", driver="GeoJSON")
layers.append(bham_bua)
glas_bua = aggregate_bua_by_mask(gcr_lads, "Glasgow (BUA 2022 aggregate)")
glas_bua.to_file("glasgow_bua_aggregate.geojson", driver="GeoJSON")
layers.append(glas_bua)
edi_bua = aggregate_bua_by_mask(edi_lad, "Edinburgh (BUA 2022 aggregate)")
edi_bua.to_file("edinburgh_bua_aggregate.geojson", driver="GeoJSON")
layers.append(edi_bua)
cdf_bua = aggregate_bua_by_mask(cdf_lad, "Cardiff (BUA 2022 aggregate)")
cdf_bua.to_file("cardiff_bua_aggregate.geojson", driver="GeoJSON")
layers.append(cdf_bua)
# ---------- Combine & report areas ----------
cities = gpd.GeoDataFrame(pd.concat(layers, ignore_index=True), crs="EPSG:4326")
# ---------- Plot UK outline + the six aggregates ----------
# UK outline (Natural Earth 1:10m, simple countries)
ne_url = "https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_10m_admin_0_countries.geojson"
world = gpd.read_file(ne_url)
uk = world[world["ADMIN"] == "United Kingdom"].to_crs(4326)
# Crop frame to our cities
minx, miny, maxx, maxy = cities.total_bounds
uk_crop = uk.cx[minx-5 : maxx+5, miny-5 : maxy+5]
fig, ax = plt.subplots(figsize=(9, 10), dpi=150)
uk_crop.boundary.plot(ax=ax, color="black", linewidth=1.2)
cities.plot(ax=ax, column="city", alpha=0.45, edgecolor="black", linewidth=0.8, legend=True)
# Label each polygon using an interior point
label_pts = cities.representative_point()
for (x, y), name in zip(label_pts.geometry.apply(lambda p: (p.x, p.y)), cities["city"]):
ax.text(x, y, name, fontsize=8, ha="center", va="center")
ax.set_title("BUA 2022 Aggregates: London, Manchester, Birmingham, Glasgow, Edinburgh, Cardiff", fontsize=12)
ax.set_xlim(minx-1, maxx+1)
ax.set_ylim(miny-1, maxy+1)
ax.set_aspect("equal", adjustable="box")
ax.set_xlabel("Longitude"); ax.set_ylabel("Latitude")
plt.tight_layout()
plt.show()
Après avoir exécuté ce code, vous devriez avoir 6 fichiers GeoJSON stockés dans votre répertoire actuel, et vous devriez également voir une sortie comme celle-ci, qui nous indique visuellement que nos fichiers de limites de ville contiennent des données valides.

Obtenir nos données sur les accidents
Notre dernière pièce du puzzle des données concerne les données sur les accidents. Le gouvernement britannique publie des rapports sur les données sur les accidents de véhicules couvrant des périodes de cinq ans. Les dernières données couvrent la période de 2019 à 2024. Cet ensemble de données couvre l’ensemble du Royaume-Uni, nous devrons donc le traiter pour extraire uniquement les données des six villes qui nous intéressent. C’est là que DuckDB entrera en jeu, mais nous y reviendrons plus tard.
Pour consulter ou télécharger les données d’accidents au format CSV (Source : Département des Transports — Données de Sécurité Routière), cliquez sur le lien ci-dessous
Comme pour les données sur les limites de la ville, celles-ci sont également publiées sous le Licence du gouvernement ouvert v3.0 (OGL 3.0) et en tant que tel, il est soumis aux mêmes conditions de licence.
Le jeu de données sur les accidents contient un grand nombre de champs, mais pour nos besoins, nous ne nous intéressons qu’à 3 d’entre eux :
latitude
longitude
number_of_casualties
Obtenir le nombre de victimes pour chaque ville n’est désormais plus qu’un processus en 3 étapes.
1/ Chargement du jeu de données d’accident dans DuckDB
Si vous n’avez jamais rencontré DuckDB auparavant, le TL;DR est qu’il s’agit d’une base de données en mémoire ultra-rapide (peut également être persistante) écrite en C++ conçue pour les charges de travail SQL analytiques.
L’une des principales raisons pour lesquelles je l’aime est sa vitesse. C’est l’une des bibliothèques d’analyse de données tierces les plus rapides que j’ai utilisées. Il est également très extensible grâce à l’utilisation d’extensions telles que celle géospatiale, que nous allons utiliser maintenant.
Nous pouvons maintenant charger les données d’accident comme ceci.
import requests
import duckdb
# Remote CSV (last 5 years collisions)
url = "https://data.dft.gov.uk/road-accidents-safety-data/dft-road-casualty-statistics-collision-last-5-years.csv"
local_file = "collisions_5yr.csv"
# Download the file
r = requests.get(url, stream=True)
r.raise_for_status()
with open(local_file, "wb") as f:
for chunk in r.iter_content(chunk_size=8192):
f.write(chunk)
print(f"Downloaded {local_file}")
# Connect once
con = duckdb.connect(database=':memory:')
# Install + load spatial on THIS connection
con.execute("INSTALL spatial;")
con.execute("LOAD spatial;")
# Create accidents table with geometry
con.execute("""
CREATE TABLE accidents AS
SELECT
TRY_CAST(Latitude AS DOUBLE) AS latitude,
TRY_CAST(Longitude AS DOUBLE) AS longitude,
TRY_CAST(Number_of_Casualties AS INTEGER) AS number_of_casualties,
ST_Point(TRY_CAST(Longitude AS DOUBLE), TRY_CAST(Latitude AS DOUBLE)) AS geom
FROM read_csv_auto('collisions_5yr.csv', header=True, nullstr='NULL')
WHERE
TRY_CAST(Latitude AS DOUBLE) IS NOT NULL AND
TRY_CAST(Longitude AS DOUBLE) IS NOT NULL AND
TRY_CAST(Number_of_Casualties AS INTEGER) IS NOT NULL
""")
# Quick preview
print(con.execute("DESCRIBE accidents").df())
print(con.execute("SELECT * FROM accidents LIMIT 5").df())
Vous devriez voir la sortie suivante.
Downloaded collisions_5yr.csv
column_name column_type null key default extra
0 latitude DOUBLE YES None None None
1 longitude DOUBLE YES None None None
2 number_of_casualties INTEGER YES None None None
3 geom GEOMETRY YES None None None
latitude longitude number_of_casualties \
0 51.508057 -0.153842 3
1 51.436208 -0.127949 1
2 51.526795 -0.124193 1
3 51.546387 -0.191044 1
4 51.541121 -0.200064 2
geom
0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, ...
1 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, ...
2 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, ...
3 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, ...
4 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, ...
2/ Chargement des données des limites de la ville à l’aide des fonctions spatiales DuckDB
La fonction que nous utiliserons pour ce faire s’appelle ST_READ, qui peut lire et importer une variété de formats de fichiers géospatiaux à l’aide de la bibliothèque GDAL.
city_files = {
"London": "london_bua_aggregate.geojson",
"Edinburgh": "edinburgh_bua_aggregate.geojson",
"Cardiff": "cardiff_bua_aggregate.geojson",
"Glasgow": "glasgow_bua_aggregate.geojson",
"Manchester": "manchester_bua_aggregate.geojson",
"Birmingham": "birmingham_bua_aggregate.geojson"
}
for city, file in city_files.items():
con.execute(f"""
CREATE TABLE {city.lower()} AS
SELECT
'{city}' AS city,
geom
FROM ST_Read('{file}')
""")
con.execute("""
CREATE TABLE cities AS
SELECT * FROM london
UNION ALL SELECT * FROM edinburgh
UNION ALL SELECT * FROM cardiff
UNION ALL SELECT * FROM glasgow
UNION ALL SELECT * FROM manchester
UNION ALL SELECT * FROM birmingham
""")
3/ La prochaine étape consiste à relier les accidents aux polygones de la ville et à compter les victimes.
La fonction géospatiale clé que nous utilisons cette fois s’appelle ST_WITHIN. Il renvoie TRUE si le premier point géométrique se trouve dans la limite du second.
import duckdb
casualties_per_city = con.execute("""
SELECT
c.city,
SUM(a.number_of_casualties) AS total_casualties,
COUNT(*) AS accident_count
FROM accidents a
JOIN cities c
ON ST_Within(a.geom, c.geom)
GROUP BY c.city
ORDER BY total_casualties DESC
""").df()
print("Casualties per city:")
print(casualties_per_city)
Notez que j’ai exécuté la requête ci-dessus sur un ordinateur de bureau puissant et qu’il a fallu encore quelques minutes pour renvoyer les résultats, alors soyez patient. Cependant, vous devriez éventuellement voir un résultat similaire à celui-ci.
Casualties per city:
city total_casualties accident_count
0 London 134328.0 115697
1 Birmingham 14946.0 11119
2 Manchester 4518.0 3502
3 Glasgow 3978.0 3136
4 Edinburgh 3116.0 2600
5 Cardiff 1903.0 1523
Analyse
Il n’est pas surprenant que Londres compte, globalement, le plus grand nombre de victimes. Mais vu sa taille, est-il plus ou moins dangereux d’y circuler en voiture ou d’y être piéton que dans les autres villes ?
Il y a clairement un problème avec le nombre de victimes à Manchester et Glasgow. Ils devraient tous deux être plus grands, en fonction de la taille de leur ville. Il semble que cela pourrait être dû au fait que bon nombre des rocades très fréquentées et des routes périphériques du métro (M8/M74/M77 ; M60/M62/M56/M61) associées à chaque ville se trouvent juste à l’extérieur de leurs polygones étroits de BUA, ce qui entraîne une sous-représentation significative des données sur les accidents et les victimes. Je laisse cette enquête comme un exercice pour le lecteur !
Pour notre détermination finale de la sécurité des conducteurs, nous devons connaître la taille de chaque ville afin de pouvoir calculer le taux de victimes par km².
Heureusement, DuckDB a une fonction pour ça. ST_AREA calcule l’aire d’une géométrie.
# --- Compute areas in km² (CRS84 -> OSGB 27700) ---
print("\nCalculating areas in km^2...")
areas = con.execute("""
SELECT
city,
ST_Area(
ST_MakeValid(
ST_Transform(
-- ST_Simplify(geom, 0.001), -- Experiment with epsilon value (e.g., 0.001 degrees)
geom,
'OGC:CRS84','EPSG:27700'
)
)
) / 1e6 AS area_km2
FROM cities
ORDER BY area_km2 DESC;
""").df()
print("City Areas:")
print(areas.round(2))
J’ai obtenu ce résultat, qui semble être à peu près correct.
city area_km2
0 London 1321.45
1 Birmingham 677.06
2 Manchester 640.54
3 Glasgow 481.49
4 Edinburgh 123.00
5 Cardiff 96.08
Nous disposons désormais de toutes les données nécessaires pour déclarer quelle ville compte les conducteurs les plus sûrs du Royaume-Uni. N’oubliez pas que plus le numéro « safety_index » est bas, plus c’est sûr.
city area_km2 casualties safety_index (casualties/area)
0 London 1321.45 134328 101.65
1 Birmingham 677.06 14946 22.07
2 Manchester 640.54 4518 7.05
3 Glasgow 481.49 3978 8.26
4 Edinburgh 123.00 3116 25.33
5 Cardiff 96.08 1903 19.08
Je ne suis pas à l’aise d’inclure les résultats de Manchester et de Glasgow en raison des doutes sur le nombre de victimes que nous avons mentionnés précédemment.
Compte tenu de cela, et parce que je suis le responsable de cet article, je déclare Cardiff gagnante du prix de la ville la plus sûre du point de vue des conducteurs et des piétons. Que pensez-vous de ces résultats ? Vivez-vous dans l’une des villes que j’ai consultées ? Si oui, les résultats confirment-ils votre expérience de conduite ou de piéton à cet endroit ?
Résumé
Nous avons examiné la faisabilité d’effectuer une analyse exploratoire des données sur un ensemble de données géospatiales. Notre objectif était de déterminer laquelle des six principales villes du Royaume-Uni était la plus sûre pour circuler en voiture ou pour piétons. En utilisant une combinaison de GeoPandas et DuckDB, nous avons pu :
- Utilisez Geopandas pour télécharger des données sur les limites de la ville à partir d’un site Web officiel du gouvernement qui représentent de manière raisonnablement précise la taille de chaque ville.
- Téléchargez et post-traitez une enquête CSV approfondie sur les accidents sur 5 ans pour obtenir les trois champs d’intérêt qu’elle contenait, à savoir la latitude, la longitude et le nombre de victimes d’accidents de la route.
- Joignez les données d’accident aux données des limites de la ville sur la latitude/longitude à l’aide des fonctions géospatiales de DuckDB pour obtenir le nombre total de victimes pour chaque ville sur 5 ans.
- Utilisation des fonctions géospatiales DuckDB pour calculer la taille en km² de chaque ville.
- Calcul d’un indice de sécurité pour chaque ville, correspondant au nombre de victimes dans chaque ville divisé par sa taille. Nous avons ignoré deux de nos résultats en raison de doutes sur l’exactitude de certaines données. Nous avons calculé que Cardiff avait l’indice de sécurité le plus bas et était donc considérée comme la plus sûre des villes que nous avons étudiées.
Avec les bonnes données d’entrée, l’analyse géospatiale à l’aide des outils que je décris pourrait être d’une aide inestimable dans de nombreux secteurs. Pensez à l’analyse de la circulation et des accidents (comme je l’ai montré), l’analyse des inondations, de la déforestation, des incendies de forêt et de la sécheresse vient également à l’esprit. Fondamentalement, tout système ou processus connecté à un système de coordonnées spatiales est mûr pour une analyse exploratoire des données par n’importe qui.



