Rechercher dans le blog

Analyse spatiale et utilisation des services de localisation avec l'API Python d'ArcGIS

C'est déjà l'heure du septième tutoriel de la série de l'été consacrée à la prise en main de l'API Python d'ArcGIS! Cette fois-ci, nous allons utiliser l'API pour faire de l'analyse spatiale. Celle-ci permet de scripter et d'automatiser les outils de géotraitement du portail ainsi que l'utilisation des services de localisation d'ArcGIS. Nous apprendrons à nous en servir pour du géocodage simple, du géocodage d'adresses par lot, du calcul d'isochrones et du calcul d'itinéraires.  

Comme chaque semaine, vous pouvez suivre le tutoriel ci-dessous pas à pas pour obtenir les explications des différentes étapes, et écrire le code par vous-même ou retrouver le code complet et commenté sur mon Github ou alors le récupérer via cet item ArcGIS
Notez qu'un compte Creator ou supérieur avec des privilèges de publication de contenu sont nécessaires. Vous pouvez exécuter ce Notebook directement dans ArcGIS Notebooks sur ArcGIS Online (disponible par défaut si votre administrateur vous a accordé les droits nécessaires), dans ArcGIS Enterprise (disponible avec le rôle serveur correspondant) ou en le téléchargeant et en l'ouvrant sur ArcGIS Pro (plus d'infos dans la doc). Vous pouvez également l'exécuter dans n'importe quel environnement d'exécution de votre choix, mais veillez dans ce cas à avoir installé les packages nécessaires.

1 - Import des bibliothèques et connexion au GIS

Nous commençons par importer les différentes bibliothèques nécessaires.
Durant ce tutoriel, nous allons utiliser les services de localisation d'ArcGIS. Nous allons géocoder 43 adresses, faire un calcul d'isochrones et calculer 3 routes, ce qui devrait consommer au total moins de 5 crédits si vous consommez via les services ArcGIS Online, et est inclus dans les transactions gratuites si vous consommez via un compte développeur sur le site ArcGIS Location Platform. Pour connaître le prix des transactions de services, vous pouvez vous référer à la documentation pour la consommation de crédits, et dans l'onglet Pricing du site ArcGIS Location Platform si vous consommez en pay-as-you-use.
  • Si vous êtes utilisateur ArcGIS Online, vous pouvez vous connecter via votre compte d'utilisateur, et vous allez consommer les crédits de votre compte ArcGIS Online. Vous pouvez également choisir d'utiliser une clé d'API pour vous connecter. Cette option est pratique si vous souhaitez pouvoir suivre la consommation de crédits de vos scripts.
  • Si vous êtes utilisateur ArcGIS Enterprise, la connexion utilisateur fonctionnera uniquement si votre portail est configuré pour pouvoir consommer les services d'ArcGIS. Si ça n'est pas le cas, sachez que vous pouvez créer un compte développeur gratuitement sur le site ArcGIS Location Platform et accéder aux services via une clé d'API. Le compte développeur vous permet d'effectuer gratuitement un certain nombre de transactions de services, ce qui devrait être suffisant pour suivre le tuto.
Pour apprendre à configurer une clé d'API, vous pouvez vous rendre sur cet article. Vous aurez besoin d'activer les privilèges de géocodage et de calcul d'itinéraires simples.
 

Connexion par utilisateur

La connexion est à adapter selon votre environnement et votre méthode d'authentification. Voir l'aide en ligne pour plus d'informations.
Si vous êtes connectés en tant qu'admin, la cellule va vous renvoyer un message rouge pour vous prévenir qu'il faut faire attention aux opérations que vous utilisez. Cela n'empêche pas votre code de s'exécuter correctement.

Connexion par clé d'API

1/ Géocodage d'une adresse simple

Le géocodage permet de trouver un point XY à partir d'une adresse. Cela peut permettre d'afficher sur une carte un endroit dont ne vous possédez pas les coordonnées, mais seulement l'adresse ou le nom du lieu. Pour utiliser le service de géocodage d'ArcGIS dans l'API Python, nous devrons faire appel au module geocoding dont nous avons importé les classes nécessaires dans la première cellule de ce Notebook.
Je vais utiliser le géocodage pour afficher mon adresse sur une carte. Pour un géocodage simple, nous utiliserons la fonction geocode().
Je passe mon adresse en argument sous la forme d'une chaîne de caractères. Le paramètre max_location me permet de définir le maximum de lieux renvoyés par le service de géocodage. En le réglant sur 1, je demande à ce que seule la correspondance la plus pertinente soit renvoyée. Enfin, grâce à as_featureset=True, la méthode retournera un FeatureSet à la place d'une liste, ce qui sera plus pratique pour la manipulation dans mon SIG (affichage sur une carte, analyse, etc.).
Nous pouvons vérifier que le type de données renvoyé est bien un FeatureSet :
Vérifions maintenant nos résultats sur une carte. Nous allons créer une carte puis y ajouter le résultat du géocodage, comme nous avons appris à le faire dans ce tutoriel. Si votre environnement est compatible, il devrait afficher la carte de manière interactive comme cela :

2/ Calcul d'isochrones

Maintenant que j'ai localisé mon adresse sur la carte, j'aimerais savoir dans quels endroits je peux me rendre à pieds et en combien de temps depuis chez moi. Pour cela, l'API Python met à disposition la fonction create_drive_time_areas() dans du module use_proximity que nous avons importé au début du Notebook.
Comme entrée, create_drive_time_areas() accepte des données au format FeatureCollection. Nous pouvons très facilement créer une FeatureCollection à partir de notre FeatureSet grâce à la méthode from_featureset() des FeatureCollection :
Nous pouvons désormais calculer les isochrones. En entrée de create_drive_time_areas(), nous passons la FeatureCollection contenant notre adresse fraîchement créée. Ce point sera le centre des isochrones.
Nous pouvons choisir un mode de déplacement grâce à travel_mode qui peut prendre la valeur de votre choix parmi la liste suivante : ["Driving Distance", "Driving Time", "Rural Driving Distance", "Rural Driving Time", "Trucking Distance", "Trucking Time", "Walking Distance", "Walking Time"] Vous voyez que nous avons le choix entre un calcul en distance ou en temps, et entre différents moyens de transport. Pour notre part, nous utiliserons le temps de marche "Walking Time".
break_values est aussi un paramètre intéressant car il me permet de choisir le temps ou la distance des isochrones. Ici, je choisis 10, 20, 30 et 60 minutes de marche. L'unité des break_values est fixée par le paramètre break_units qui peut prendre les valeurs suivantes, en distance ou en temps : ["Seconds", "Minutes", "Hours", "Feet", "Meters", "Kilometers", "Feet", "Miles", "Yards"].
Nous pouvons aussi indiquer un système de projection (ici WGS84 avec le wkid 4326) pour les entités en sortie avec la paramètre context. La fonction renverra un FeatureLayer, qui sera enregistré dans mon contenu sur mon portail. Je peux choisir son nom en renseignant le paramètre output_name.
Comme pour tous les éléments de mon portail que j'ai stockés dans une variable dans mon script, je peux facilement accéder à l'item interactivement dans mon Notebook en rappelant la variable. Cela me permet d'aller le consulter : 
Et nous pouvons également l'ajouter à notre carte :
Voici le résultat :

3/ Géocodage par lot de plusieurs adresses

C'est bien de savoir jusqu'à où je peux aller en marchant, mais ça serait mieux qu'il y ait 2-3 trucs à faire sur la route, comme par exemple manger. La bonne nouvelle, c'est que j'ai en ma possession une liste de restaurants avec leurs adresses trouvé sur datagouv. J'ai hebergé le csv de cette liste de restaurants à l'adresse suivante : https://raw.githubusercontent.com/JapaLenos/Python-in-ArcGIS/main/Prise-en-main-API-Python/Tuto7-analyse-services-localisation/restaurants_paris.csv. Je peux ensuite lire le csv en tant que Dataframe, et supprimer les lignes contenant les valeurs vides comme nous l'avions appris dans ce tutoriel.
Cette fois-ci, nous n'allons pas géocoder une seule adresse mais plusieurs adresses par lot, aussi appelé en batch. Pour cela, nous devrons cette fois-ci utiliser la fonction batch_geocode(), toujours du module geocoding.
La documentation m'indique que ma liste d'adresses peut être formatée de la manière suivante : addresses= [{“Address”: “380 New York St.”, “City”: “Redlands”, “Region”: “CA”, “Postal”: “92373”},{ “Address”: “1 World Way”, “City”: “Los Angeles”, “Region”: “CA”, “Postal”: “90045”}]. Dans notre jeu de données, nous n'aurons pas les informations sur la région mais ça n'est pas grave, notez plus que plus d'informations vous avez sur l'adresse, plus cela pourra aider le géocodeur à faire un choix entre 2 adresses pouvant exister dans 2 villes différentes par exemple.
Je manipule mon DataFrame pour en obtenir une liste interprétable par la fonction :
Je peux maintenant utiliser la fonction batch_geocode() en passant ma liste d'adresses en argument. A nouveau, j'utilise le paramètre as_featureset que la fonction retourne un FeatureSet.
J'affiche le résultat sur la carte :

4/ Sélection spatiale

Je vais maintenant récupérer uniquement les restaurants situés à maximum 20 minutes de chez moi. Ce sont les restaurants situé à l'intérieur du premier ou du second isochrone. Pour faire cela avec l'API Python d'ArcGIS, le plus facile est d'utiliser la géométrie de mes données en accédant à celle-ci via un Spatially enabled DataFrame (SeDF). Si ce que je dis vous paraît totalement exotique, c'est que vous n'avez pas suivi le tutoriel #5 de la série, que je vous conseille fortement (j'ai entendu dire qu'il était plutôt pas mal).
Pour accéder aux données de géocodage des restaurants sous la forme d'un SeDF, je peux accéder à la propriété sdf du FeatureSet :
Pour obtenir un SeDF à partir des données d'isochrones, la manipulation est cette fois-ci légèrement différente puisqu'il s'agit d'un FeatureLayer. Je peux lire celui-ci sous la forme d'un SeDF grâce à la méthode from_layer() dans laquelle je passe en argument mon FeatureLayer.

Les isochrones contenant les temps de marche de 0 à 10min et de 10 à 20min sont contenues dans les deux dernières lignes du SeDF, donc aux index 3 et 2. J'accède à leur géométrie contenue dans la colonne SHAPE :
La méthode disjoint() permet de comparer deux géométries, et renvoie une série de booléens : True si les sont géométries des entités comparées sont disjointes (ne s'intersectent pas) et False sinon (les données s'intersectent). == False me permet ensuite d'inverser le résultat, et de passer à True les géométries non disjointes et à False les géométries disjointes. J'utilise donc cette méthode sur la géométrie du sedf contenant les restaurants, et passe en argument la géométrie du sedf contenant les limites de bordeaux récupérée au-dessus.
Je le fais consécutivement sur les 2 isochrones, puis je combine le résultat des 2 requêtes, et obtiens la valeur True pour tous les restaurants situés à 20 minutes à pieds ou moins.
J'utilise ensuite cette série booléenne pour filtrer le dataframe des compteurs de trafic. En passant la série en entrée de la propriété loc de mon dataframe, j'accède uniquement aux lignes pour lesquelles la valeur du booléen est True. La fonction copy() permet de créer une copie du dataframe filtré, afin d'éviter les problèmes liés à la modification d'une vue sur l'original.
Nous pouvons afficher les résultats sur la carte :

5/ Calcul d'itinéraires

Je vais maintenant calculer les itinéraires pour me rendre dans chacun des 3 restaurants situés à moins de 20 minutes à pieds. Comme tout à l'heure, nous allons utiliser une fonction du module use_proximity. Il s'agit cette fois-ci de connect_origins_to_destinations(), qui prend elle aussi en entrée des données de type FeatureCollection. Je convertis donc mon SeDF en FeatureCollection, en passant par l'étape FeatureSet.
Nous pouvons désormais appeler connect_origins_to_destinations(). En couche d'origine (point(s) de départ de(s) l'itinéraire(s)), je transmets mon adresse au format FeatureCollection , et en couche de destination (point(s) d'arrivée de(s) l'itinéraire(s)) les restaurants proches, dans le même format. A nouveau, il est possible de choisir le mode de transport parmi les éléments de la liste suivante : ["Driving Distance", "Driving Time", "Rural Driving Distance", "Rural Driving Time", "Trucking Distance", "Trucking Time", "Walking Distance", "Walking Time"]. Je choisis une distance de marche. Enfin, la fonction va publier les résultats sous forme d'un FeatureLayer dans mon contenu, dont je peux choisir le nom.
J'ajoute l'item fraîchement créé à la carte :
Dans ce tutoriel, nous avons vu deux fonctions du module use_proximity. Sachez que ce module met à disposition d'autres outils accessibles sous la forme de fonctions que vous pourrez retrouver dans la doc.
Notez également que ce module ne représente que l'une des boites à outils disponibles (en l'occurence regroupant les outils d'analyse de proximité), mais vous pourrez en retrouvez de nombreuses autres vous permettant de faire d'autres types d'analyses spatiales (analyse de tendances dans les données, analyse de l'élévation, synthèse des données, analyses de l'hydrologie,...) Je vous invite à consulter la documentation pour découvrir tout cela.

6/ Publication des résultats

Les résultats des calculs d'isochrones et d'itinéraires sont d'ores et déjà enregistrés, mais j'aimerais aussi conserver les résultats du géocodage. La manière la plus simple pour cle est d'accéder aux données sous forme de Spatially enabled Dataframe puis de les publier. Le SeDF des restaurants et celui des restaurants proches existe déjà, je n'ai plus qu'à créer et stocker le dernier, celui de mon adresse, dans une variable :
Je créée ensuite une liste de listes contenant chacune la variable contenant un des SeDF ainsi que le nom que je souhaite donner au FeatureLayer une fois qu'il sera publié : 
Je peux ensuite itérer dans la liste, et publier chacun des SeDF grâce à la méthode to_featurelayer() :
Voilà, c'est fini pour ce tutoriel ! Bon, il est temps de tout vous avouer.... Depuis le début, l'adresse utilisée n'est en réalité pas ma vraie adresse. Eh oui, c'est décevant, mais je n'ai malheureusement pas les moyens d'habiter au Ritz. J'espère que cela ne vous empêchera pas de continuer à suivre la série ! Dans le prochain épisode, nous apprendrons à publier ce genre de Notebook en tant qu'outil de géotraitement.

Aucun commentaire:

Enregistrer un commentaire