Je poursuis ma série de tutoriels consacrés à l'usage de l'API ArcGIS for Python. Aujourd'hui, je vous propose de voir un ensemble d'instructions permettant la modification des données des couches d'entités de votre portail ArcGIS. Le tutoriel ci-dessous montre également comment modifier la structure des couches.
Le Notebook présenté ci-dessous est téléchargeable ici.
Ce tutoriel a pour objectif d'illustrer les possibilités de l'API Python ArcGIS en termes de mise à jour des données et de la structure des couches d'entités hébergées sur votre portail ArcGIS. A l'aide des exemples de code ci-dessous, vous pourrez élaborer des scripts plus évolués automatisant la mise à jour des données de vos couches, l'ajout et le calcul de champs, l'ajout de domaines de valeurs, de pièces jointes, ...
In [81]:
from IPython.display import display
from arcgis.gis import GIS
my_gis = GIS('https://www.arcgis.com', 'username', 'password')
In [82]:
my_gis
Out[82]:
Lister les champs d'une couche d'entités¶
Commençons tout d'abord par récupérer la couche d'entités. Par exemple, en utilisant son "ItemID".
In [83]:
my_item = my_gis.content.get('5f227e966acf46d7b2b254f2af85a27e')
my_item
Out[83]:
La séquence d'instructions suivante permet de récupérer la liste des champs de la couche d'entités hébergée.
In [84]:
from arcgis.features import FeatureLayer
my_FL = FeatureLayer.fromitem(my_item,0)
my_fields = my_FL.properties.fields
Profitons-en pour utiliser les capacités de présentation de Jupyter pour présenter cette liste en exploitant les capacités de la syntaxe Markdown !
In [46]:
from IPython.display import Markdown, display
strMarkdown = "Name | Alias | Type | SQL Type"
strMarkdown += "\n" + "-|-|-|-"
for field in my_fields:
strMarkdown += "\n" + field.name + " | " + field.alias + " | " + field.type + " | " + field.sqlType
display(Markdown(strMarkdown))
Supprimer un champ¶
Nous souhaitons maintenant supprimer le champ "Ancien_ID". Pour cela, nous devons tout d'abord créer un objet JSON décrivant la propriété "name" du champ (ou des champs) à supprimer. Ensuite, la méthode "delete_from_definition" de l'objet "FeatureLayerManager" va vous permettre de supprimer effectivement le(s) champ(s) de la couche d'entités ou de la table.
In [47]:
field_to_delete = {'name': 'Ancien_ID'}
my_FL.manager.delete_from_definition({'fields':[field_to_delete]})
Out[47]:
Reprenons le code précédement utiliser pour accéder à la couche d'entités et lister à nouveau les champs. Le champ "Ancien_ID" a bien été supprimé.
In [48]:
my_FL = FeatureLayer.fromitem(my_item,0)
my_fields = my_FL.properties.fields
strMarkdown = "Name | Alias | Type | SQL Type"
strMarkdown += "\n" + "-|-|-|-"
for field in my_fields:
strMarkdown += "\n" + field.name + " | " + field.alias + " | " + field.type + " | " + field.sqlType
display(Markdown(strMarkdown))
Ajouter un nouveau champ¶
L'objectif est de créer un nouveau champ dans lequel nous allons calculer le ratio entre le nombre d'entrée et le nombre de séances dans chaque cinéma. La première étape consiste à décrire, en JSON, les propriétés du nouveau champ. Se référer à la documentation de l'API Rest ArcGIS pour obtenir la liste des propriétés et valeurs supportées.
In [49]:
new_field={'alias': 'Ratio des Entrees-Seances',
'domain': None,
'editable': True,
'length': 10,
'name': 'ratio_entrees_seances',
'nullable': True,
'sqlType': 'sqlTypeOther',
'type': 'esriFieldTypeDouble'}
Ensuite, vous utiliserez la méthode "add_to_definition" de l'objet "FeatureLayerManager" pour spécifier la liste des nouveaux champs à ajouter à la définition de la couche d'entités (ou de la table).
In [50]:
my_FL.manager.add_to_definition({'fields':[new_field]})
Out[50]:
Vérifions que le champ a bien été ajouté en affichant le dernier champ de la table attributaire de la couche.
In [51]:
my_FL = FeatureLayer.fromitem(my_item,0)
my_fields = my_FL.properties.fields
last_field=my_fields[len(my_fields)-1]
last_field
Out[51]:
Associer un domaine de valeurs à un champ¶
Les champs d'une couche d'entités hébergée peuvent être associés à des listes de valeurs, l'équivalents des domaines de valeurs dans les Géodatabases. Voyons comment ajouter une liste de valeurs à un champ en utilisant l'API Python ArcGIS.
Tout d'abord, vous décrirez l'objet JSON du champ que vous voulez mettre à jour, en décrivant le domaine comme ci-dessous. Vous noterez que l'on ne décrit pas totalement l'objet "field", uniquement la propriétés "name" et les autres propriétés devant être modifiées, ici la propriété "domain":
In [91]:
updated_field={
'name': "Categorie_Art_et_Essai",
'domain': {
'type': "codedValue",
'name': "Categorie_Art_et_Essai_Domain",
'codedValues': [
{
'name': "Non classé",
'code': "Non classé"
},
{
'name': "Catégorie A",
'code': "Catégorie A"
},
{
'name': "Catégorie B",
'code': "Catégorie B"
}
]
},
'defaultValue': "Non classé"
}
A l'aide de la méthode "update_definition" vous appliquerez les modifications sur votre champ.
In [92]:
my_FL.manager.update_definition({'fields':[updated_field]})
Out[92]:
Calculer les valeurs d'un champ¶
Commençons par un premier exemple dans lequel nous souhaitons mettre le champ AE (Année Exploitation) à 2017 pour les cinémas d'Ile-de-France et 2016 pour les autres régions:
In [52]:
my_FL.calculate("Region LIKE 'ILE-DE-FRANCE'",{"field": "AE", "value" : "2017"})
Out[52]:
In [53]:
my_FL.calculate("Region NOT LIKE 'ILE-DE-FRANCE'",{"field": "AE", "value" : "2016"})
Out[53]:
Ci-dessous, un deuxième exemple visant à calculer la valeur du champ "ratio_entrees_seances" par une division du nombre d'entrées par le nombre de séances, tout cela à l'aide d'une expression SQL. Le calcul sera, cette fois-ci, appliqué à tous les enregistrements de la couche d'entités:
In [54]:
my_FL.calculate("1=1",{"field": "ratio_entrees_seances", "sqlExpression" : "CAST(Entrees AS FLOAT) / CAST(Seances AS FLOAT)"})
Out[54]:
Ajouter une entité à votre couche¶
Pour ajouter un nouvel enregistrement dans une couche d'entités, il vous faut tout d'abord créer l'objet "Feature" en JSON. Vous noterez que dans notre exemple, ne n'avons pas listé et renseigné tous les champs de la table.
In [55]:
new_feature={"geometry": {"y": 68540528, "x": 6404123},
"attributes": {"Nom": "CINEMA UGC VELIZY2","Commune": "Vélizy-Villacoublay", "Code_Insee": "78640",
"Region": "ILE-DE-France", "Fauteuils": 750, "Seances": 12}}
La méthode "edit_features" permet d'exécuter l'opération de mise à jour. On notera que l'argument "adds" permet de fournir plusieurs entités à l'aide d'un tableau d'objet "feature". A noter également que cette méthode "edit_feature" permet en une seule opération de réaliser des ajouts, des mises à jour et des suppressions.
In [56]:
my_FL.edit_features(adds=[new_feature])
Out[56]:
Mettre à jour une entité de votre une couche¶
Pour mettre à jour des entités existantes, il vous faudra tout d'abord les récupérer, par exemple, à l'aide d'une requête ci-dessous. A noter que l'on peut aussi construire entièrement (ou partiellement) l'objet "feature" en JSON.
In [57]:
my_featureset = my_FL.query(where="Nom LIKE 'CINEMA UGC VELIZY2'")
feature_to_update = my_featureset.features[0]
Mettre ensuite à jour les différents attributs de ces entités.
In [58]:
feature_to_update.attributes['Adresse']='Centre commercial Vélizy 2'
feature_to_update.attributes['Multiplexe']='Oui'
Nous utilisons à nouveau la méthode "edit_features" avec l'argument "updates" pour mettre à jour la liste d'objets "feature" à actualiser dans la couche d'entités.
In [59]:
my_FL.edit_features(updates= [feature_to_update])
Out[59]:
Supprimer une entité dans une couche¶
La suppression d'une (ou plusieurs) entité(s) se fait de différentes manières. Vous pouvez utiliser, comme précédement, la méthode "edit_features" peut être utilisée en fournissant la liste des entités en JSON avec leur propriété "ObjectId". Vous pouvez également utiliser la méthode "delete_features" et fournir une requête définissant les entités à supprimer.
In [60]:
my_FL.delete_features(where="Nom LIKE 'CINEMA UGC VELIZY2'")
Out[60]:
Activer les pièces-jointes sur une couche d'entité¶
Pour pouvoir ajouter des pièces-jointes (attachments en anglais) aux entités de votre couche, vous devez tout d'abord activer le stockage des pièces-jointes sur la couche. Pour cela, nous passons à nouveau par la modification de la définition de la couche.
In [61]:
attachment_JSON={'hasAttachments': True}
my_FL.manager.update_definition(attachment_JSON)
Out[61]:
Ajouter des pièces-jointes¶
Maintenant que la couche dispose de la structure pour le stockage de pièces-jointes, la méthode "add" sur la propriété "attachments" permet d'ajouter votre fichier. Vous noterez que le premier argument de la méthode "add" correspond à l'objectID de l'entité. Recherchons le cinéma "Caméo Commanderie" à Nancy pour lui associer une photo.
In [62]:
my_featureset = my_FL.query(where="Nom LIKE 'Caméo Commanderie Nancy'")
feature_oid = my_featureset.features[0].get_value('objectId')
my_FL.attachments.add(feature_oid, '/Users/glavenu/Documents/SIG/temp/cameo_nancy.jpg')
Out[62]:
Lister les pièces-jointes d'une entité¶
Pour lister les pièces-jointes d'une entité, il suffira de rechercher l'entité puis d'utiliser la méthode
In [65]:
my_featureset = my_FL.query(where="Nom LIKE 'Kinépolis Nancy'")
feature_oid = my_featureset.features[0].get_value('objectId')
my_attachements=my_FL.attachments.get_list(feature_oid)
my_attachements
Out[65]:
Supprimer des pièces-jointes¶
Ci-dessous, un exemple de code permettant de supprimer la dernière pièce-jointe de l'entité listé précédement. . La méthode "delete" appliquée à la propriété "attachments" permet de supprimer une pièce jointe en précisant l'ObjectID de l'entité et l'ID de la pièce-jointe.
Pour mémoire, en Python, l'index -1 permet d'accéder au dernier élément d'un tableau ou d'une liste
Pour mémoire, en Python, l'index -1 permet d'accéder au dernier élément d'un tableau ou d'une liste
In [66]:
my_FL.attachments.delete(my_attachements[-1]['parentObjectId'],my_attachements[-1]['id'])
Out[66]:
In [68]:
my_attachements=my_FL.attachments.get_list(feature_oid)
my_attachements
Out[68]:
Télécharger les pièces-jointes¶
Pour être complet sur la manipulation des pièces-jointes, vois les instruction permettant de les télécharger en local.
In [79]:
img=my_FL.attachments.download(oid=feature_oid, attachment_id=4)
img
Out[79]:
Si la pièce-jointe est une image et que vous souhaitez la visualiser dans votre Notebook, vous pouvez utiliser les instructions suivantes:
In [80]:
from IPython.core.display import Image, display
img_path=img[0]
display(Image(img_path))

0 comments :
Enregistrer un commentaire