Je poursuis ma série de tutoriels consacrés à l'usage de l'API ArcGIS for Python. Aujourd'hui, je vous propose de voir comment automatiser la mise à jour et/ou l'ajout de données en "batch" sur vos couches d'entités ou tables hébergées sur votre portail ArcGIS. Le tutoriel montre également comment supprimer tout ou partie des enregistrements de votre couche d'entités (ou de votre table).
Le Notebook présenté ci-dessous est téléchargeable ici.
Tuto 5: Compléter ou modifier les données de vos couches d'entités en "batch"¶
Dans ce tutoriel, nous allons voir comment écraser ou mettre à jour par lot les données d'une couche d'entités (ou d'une table). ArcGIS Online permet en effet de compléter ou de mettre à jour les données d'une couche en une seule opération. Si votre jeu de données est régulièrement complété ou modifié, vous pourrez automatiser avec l'API Python ArcGIS le processus d'actualisation sans avoir à supprimer, rechercharger et republier les données à chaque mise à jour.
In [35]:
fromIPython.displayimportdisplay
fromarcgis.gisimportGIS
my_gis=GIS('https://www.arcgis.com','username','password')
In [36]:
my_gis
Out[36]:
Publication initiale de la couche¶
Considérons un fichier CSV contenant les localisations (latitude, longiture) des radars routiers fixes en France en 2017. Pour publier le service, vous devrez tout d'abord ajouter cette source de données à vos contenus sur le portail. Pour cela, vous récuperez l'objet "ContentManager" puis la méthode "add".
In [45]:
data_file="/Users/glavenu/Documents/SIG/temp/radars.csv"
csv_item=my_gis.content.add({'title':'Les radars en France',
'tags':'Radars,Sécurité routière,France'},
data_file)
csv_item
Out[45]:
La méthode "publish" permet ensuite de publier un service d'entités depuis cette source de données.
In [46]:
my_lyr=csv_item.publish({"name":"Les_radars_en_France",
"title":"Les radars en France",
"locationType":"coordinates",
"latitudeFieldName":"latitude",
"longitudeFieldName":"longitude"})
my_lyr.update(thumbnail='/Users/glavenu/Documents/SIG/temp/radars.png')
my_lyr
Out[46]:
Pour rappel, pour modifier les privilèges d'accès à cette couche, la méthode "share" vou permettra de définir le niveau de partage. Ici, l'élément est partagé avec les membres de l'organisation appartenant au groupe "Démo".
In [50]:
my_lyr.share(everyone=False,org=False,groups='Démo',allow_members_to_edit=False)
Out[50]:
Compléter et modifier les données de la couche d'entités¶
Imaginons maintenant que vous souhaitiez ajouter un deuxième fichier CSV contenant à la fois des modifications sur certains radars existants et les nouveaux radars installés depuis janvier 2018.
Comptons le nombre d'entités de la couche.
In [51]:
fromarcgis.featuresimportFeatureLayer
my_FL=FeatureLayer.fromitem(my_lyr)
update_indexes={'name':'id_Index','fields':'id','isAscending':False,'isUnique':True,'description':''}
my_FL.manager.add_to_definition({'indexes':[update_indexes]})
my_query_result=my_FL.query(where="1=1",return_count_only=True)
my_query_result
Out[51]:
Les instructions qui vont suivre vont permettre d'ajouter de nouvelles entités dans la couche d'entités mais également de modifier des entités existantes, notamment celle-ci possédant l'ID 15825:
In [52]:
my_query_result=my_FL.query(where="id=15825")
my_query_result.features[0]
Out[52]:
Ajoutons maintenant le nouveau jeu de données. Quelle que soit la source de données initiale, celui-ci peut être dans n'importe lequel des formats suivants: sqlite, shapefile, filegdb, featureCollection, geojson, csv ou excel.
In [53]:
data_file="/Users/glavenu/Documents/SIG/temp/radars_2018.csv"
csv_item=my_gis.content.add({'title':'MAJ Radars 2018',
'tags':'Radars,Sécurité routière,France'},
data_file)
csv_item
Out[53]:
L'ID de ce nouvel élément sera nécessaire pour ajouter cette source de données... et pour la supprimer une fois le service d'entités actualisé
In [54]:
csv_item.id
Out[54]:
Avant de pouvoir ajouter la source de données, pour les fichiers CSV ou Excel, cette source de données doit être analysée afin de déterminer les champs qu'elle contient et les informations de localisation à utiliser pour mettre à jour la couche cible. Dans notre cas, les champs "latitude" et "longitude" seront pas défaut utilisés.
In [55]:
my_gis.content.analyze(item=csv_item.id)['publishParameters']
Out[55]:
La méthode "append" permet d'ajouter et/ou de modifier des entités dans la couche d'entités cible. Vous indiquerez notamment les champs de la source à ajouter ("append_fields") avec ceux déjà existants dans la couche cible (field_mapping). Le paramètre "source_info" correspond aux informations de publication (nécessaire ici car le format est un CSV). Dernier paramètre indispensable, le paramètre "upsert_matching_field" permet de spécifier le champ identiant dans la couche cible qui permettra la mise en correspondance avec les enregistrements de la table à ajouter.
In [56]:
my_FL.append(item_id=csv_item.id,upload_format='csv',source_table_name=None,
field_mappings=["date_heure_creation","date_heure_dernier_changement","date_installation","id","direction","emplacement","equipement","latitude","longitude","route","type","vitesse_vehicules_legers_kmh","ObjectId"],
source_info=my_gis.content.analyze(item=csv_item.id)['publishParameters'],
upsert=True,skip_updates=False,update_geometry=True,
append_fields=["date_heure_creation","date_heure_dernier_changement","date_installation","id","direction","emplacement","equipement","latitude","longitude","route","type","vitesse_vehicules_legers_kmh","ObjectId"],
rollback=True,skip_inserts=False,upsert_matching_field="id")
Out[56]:
Vérifions tout d'abord le nombre d'entités désormais présentes dans la couche. On constate que 29 entités ont été ajoutées.
In [57]:
my_query_result=my_FL.query(where="1=1",return_count_only=True)
my_query_result
Out[57]:
Vérifions que les attributs de l'entité possédant l'ID 15825 ont bien été actualisés.
In [58]:
my_query_result=my_FL.query(where="id=15825")
my_query_result.features[0]
Out[58]:
Maintenant que la source de données CSV a été utilisée pour compléter et mettre à jour la couche d'entités, elle peut être supprimée du portail.
In [59]:
csv_item.delete()
Out[59]:
Remplacer l'intégralité des données d'une couche d'entités¶
Dans certains cas d'usage vous pouvez avoir besoin, régulièrement et de manière autiomatisée, d'écraser la totalité des données d'une couche d'entités (ou d'une table) hébergée sur votre portail. Il existe une manière très simple de le faire en utilisant les instructions suivantes:
Commençons par charger une nouvelle source de données (ici un Shapefile) avec les informations démographiques sur le département de la Somme.
In [90]:
data_file="/Users/glavenu/Documents/SIG/temp/DEMOGRAPHIE_2016.zip"
shp_item=my_gis.content.add({'title':'Démographie des communes de la Somme - 2016',
'tags':'Démographie,Haut-de-France,Somme'},
data_file)
Publions cette source de données en tant que couche d'entités.
In [91]:
my_shp_lyr=shp_item.publish({'name':'Demographie_Communes_Dept_Somme',
'title':'Démographie des communes de la Somme - 2016',
'tags':'Démographie,Haut-de-France,Somme'})
my_shp_lyr
Out[91]:
Pour pouvoir écraser vos données, vous devez disposer du nouveau fichier source (ici le shapefile contenant les données démographiques de 2017) et instancier l'objet "FeatureLayerCollectionManager" correspondant à votre couche d'entités. Ce dernier est instancié grâce à l'URL du service d'entités de votre couche.
In [92]:
new_data_file="/Users/glavenu/Documents/SIG/temp/DEMOGRAPHIE_2017.zip"
In [93]:
fromarcgis.features.managersimportFeatureLayerCollectionManager
my_FLCollectionManager=FeatureLayerCollectionManager(my_shp_lyr.url,my_gis)
Une fois l'objet "FeatureLayerCollectionManager" instancié, la méthode "overxrite" vous permettra de remplacer la totalité des données de votre couche.
In [94]:
my_FLCollectionManager.overwrite(data_file_overwrite)
Out[94]:
La démarche sera exactement la même avec d'autres sources de données comme un fichier GeoJSON, une Géodatabase, ... y compris si le service contient plus couches/tables. On doit cependant noter les contraintes suivantes:
- Seuls les couches d'entités et les tables hébergées peuvent être utilisées
- La source de données d'origine utilisée pour la publication du service doit toujours exister sur le portail
- La nouvelle source de données servant à écraser les données doit être dans le même format que la source de données d'origine
- Le schéma de la nouvelle source de données doit être exactement le même que la source de données d'origine. Le nombre d'enregistrement peut bien entendu être différent.
Supprimer tout ou partie d'une couche d'entités¶
Dans certains cas, votre couche d'entités peut avoir besoin d'être régulièrement vidée sans pour autant avoir besoin d'y recharger immédiatement des données. Voici deux méthodes permettant de vider tout ou partie d'une couche d'entités.
Si vous souhaitez maîtriser les entités (ou les enregistrements) à supprimer, vous pourrez utiliser la méthode "delete_features" sur votre objet "FeatureLayer" qui offre l'avantage de pouvoir spécifier une requête SQL ("where=xxx").
In [98]:
my_FL=FeatureLayer.fromitem(my_shp_lyr)
my_FL.delete_features(where="Population>100000",rollback_on_failure=True)
Out[98]:
Une autre possibilité consiste à utiliser la méthode "truncate" disponible sur l'objet "FeatureLayerManager". Dans ce cas, tous les enregistrements de la couche/table sont supprimés.
In [82]:
my_FL.manager.truncate()
Out[82]: