Depuis la version 9.2 d'ArcGIS, la calculatrice de valeurs de champs (ou l'outil de géotraitement correspondant) permet d'utiliser soit le langage VBScript soit Python pour rédiger votre expression de calcul. Même si pendant plusieurs années l'usage de l'un ou de l'autre était agnostique, il devient incontournable de laisser tomber VBScript et de rédiger désormais ses expressions de calcul en Python. Tout d'abord parce que Python offre des fonctionnalités plus puissantes mais aussi parce que VBScript n'est pas supporté dans les contextes d'exécution 64 bits:
- lors de l'utilisation de l'option d'exécution des géotraitements en arrière plan 64 bits dans ArcMap, ArcScene ou ArcGlobe.
- lors de l'utilisation des géotraitements avec ArcGIS Server (nativement 64 bits)
- lors de l'utilisation des géotraitements conjointement avec ArcGIS Pro (nativement 64 bits)
Si vous n'êtes pas encore un expert des expressions de calcul en Python, je vous propose de le devenir à l'aide de la série d'exemples qui, je l'espère, couvriront la majorité de vos besoins:
Quelques éléments de base
L'utilisation de l'outil "
Calculer un champ" disponible aussi bien dans ArcMap, ArcScene, ArcGlobe et ArcGIS Pro, permet de spécifier une expression Python pour calculer les valeurs d'un champ.
Il peut s'agir d'un calcul simple basé sur une expression rédigée sur une seule ligne.
|
Expression de calcul simple dans ArcMap |
Il peut s'agir d'un calcul plus avancé nécessitant la rédaction d'une expression et d'un bloc de code. Dans ce cas, l'expression appelle généralement une fonction (def MaFonction():) écrite en Python dans le bloc de code.
|
Expression de calcul avec bloc de code dans ArcGIS Pro |
Lors de l'utilisation d'un bloc de code, Python applique une indentation du code dans le cadre de la syntaxe pour définir les différents niveaux logiques du code. Vous devrez donc utiliser deux ou quatre espaces pour définir chaque indentation. Vous alignerez le début et la fin des blocs d'instruction en restant cohérent.
Vous noterez que les noms des champs dans les expression de calcul Python sont délimités par des points d'exclamation (!!).
Lorsque vous nommez des variables, n'oubliez pas que Python respecte la casse. Ainsi, la variable "ratio" n'est pas équivalent à la variable "Ratio".
Après la saisie des instructions, vous pouvez cliquer sur le bouton "Exporter" si vous souhaitez les enregistrer dans un fichier. Le bouton "Importer" vous invite à rechercher et sélectionner un fichier de calcul existant.
Expressions sur les chaînes de caractères
Concaténer plusieurs champs de type chaîne de caractères:
Expression:
!Mon_Champ1! + ' ' + !Mon_Champ2!
Concaténer plusieurs champs dont certains sont de type numérique (ici: le champ Hauteur):
Expression:
'La hauteur du bâtiment ' + !Id_bat! + ' est de ' + str(!Hauteur!) + ' m."
Calculer le nombre de caractères d'une chaîne:
Expression:
len(!Mon_Champ!)
Remplacer un caractère par un autre caractère:
Expression:
!Mon_Champ!.replace(u'é',u'e')
Remplacer les valeurs nulles par une chaîne vide:
Bloc de code:
def UpdateField(value):
if value is None:
return ''
else:
return value
Expression:
UpdateField(!Mon_Champ!)
Extraire le premier caractère d'une chaîne:
Expression:
!Mon_Champ![0]
Extraire le deuxième caractère d'une chaîne:
Expression:
!Mon_Champ![1]
Extraire le dernier caractère d'une chaîne:
Expression:
!Mon_Champ![-1]
Extraire l'avant-dernier caractère d'une chaîne:
Expression:
!Mon_Champ![-2]
Extraire les 5 premiers caractères d'une chaîne:
Expression:
!Mon_Champ![:5]
Extraire les 3 derniers caractères d'une chaîne:
Expression:
!Mon_Champ![-5:]
Extraire une partie quelconque d'une chaîne (ici: deuxiène, troisième et quatrième caractère):
Expression:
!Mon_Champ![1:4]
Extraire le 3ième mot d'une chaîne:
Bloc de code:
def ExtractWord(value, index):
tablo = value.split(' ')
if (len(tablo)>index):
return tablo[index-1]
else:
return None
Expression:
ExtractWord(!Mon_Champ!,3)
Extraire le 4ième mot d'une chaîne dont les mots sont séparés par une virgule:
Bloc de code:
def ExtractWord(value, index):
tablo = value.split(',')
if (len(tablo)>index):
return tablo[index-1]
else:
return None
Expression:
ExtractWord(!Mon_Champ!,4)
Retirer les espaces inutiles en fin de chaîne:
Expression:
!Mon_Champ!.rstrip()
Retirer les espaces inutiles en début de chaîne:
Expression:
!Mon_Champ!.lstrip()
Retirer les espaces inutiles en début et fin de chaîne:
Expression:
!Mon_Champ!.strip()
Retirer les espaces, tabulations, sauts de ligne et retours chariot en début et fin de chaîne:
Expression:
!Mon_Champ!.strip(' \t\n\r')
Mettre tout en minuscule:
Expression:
!Mon_Champ!.lower()
Mettre tout en majuscule:
Expression:
!Mon_Champ!.upper()
Mettre le premier caractère en majuscule et le reste en minuscule:
Expression:
!Mon_Champ!.capitalize()
Mettre une majuscule au début de chaque mot:
Expression:
!Mon_Champ!.title()
Insérer une simple-quote dans une chaîne:
Expression:
'Voici l\'insertion d\'une apostrophe'
Insérer une double-quote dans une chaîne:
Expression:
'Voici \"la citation\"'
Choisir une chaîne de manière aléatoire parmi une liste de chaîne:
Bloc de code:
import random
mylist = ['Pomme','Poire','Orange','Kiwi','Fraise']
Expression:
mylist[random.randrange(len(mylist))]
Expressions sur les valeurs numériques
Convertir une chaîne en entier court:
Expression:
int(!Mon_Champ_Text!)
Convertir une chaîne en entier long:
Expression:
long(!Mon_Champ_Text!)
Convertir une chaîne en nombre décimal:
Expression:
float(!Mon_Champ_Text!)
Remplacer les valeurs nulles par la valeur 0:
Bloc de code:
def UpdateField(value):
if value is None:
return 0
else:
return value
Expression:
UpdateField(!Mon_Champ!)
Arrondir à l'entier inférieur ou supérieur selon les règles mathématiques classiques:
Expression:
round(!Mon_Champ_Decimal!)
Arrondir à l'entier supérieur:
Expression:
math.ceil(!Mon_Champ_Decimal!)
Arrondir à l'entier inférieur:
Expression:
math.floor(!Mon_Champ_Decimal!)
Arrondir à la 3ème décimale:
Expression:
round(!Mon_Champ_Decimal!,3)
Générer un nombre entier aléatoire entre 0 et 9:
Bloc de code:
import random
Expression:
random.randint(0,9)
Générer un nombre décimal aléatoire entre 0 et 1:
Bloc de code:
import random
Expression:
random.random()
Générer un nombre décimal aléatoire entre 20 et 80:
Bloc de code:
import random
Expression:
20 + (random.random()*60)
Calculer la valeur absolue d'un nombre:
Expression:
math.fabs(!Mon_Champ!)
Calculer l'opposé d'un nombre:
Calculer le modulo d'un nombre:
Expression:
!Mon_Champ_Decimal! % 360
Calculer le carré d'un nombre:
Expression:
!Mon_Champ! ** 2
Calculer le cube d'un nombre
Expression:
!Mon_Champ! ** 3
Calculer la racine carrée d'un nombre
Expression:
!Mon_Champ! ** (1./2.)
Calculer la racine cubique d'un nombre
Expression:
!Mon_Champ! ** (1./3.)
Calculer le volume d'une sphère à partir du champ contenant le rayon (utilisation de la constant Pi):
Expression:
4.0 / 3.0 * math.pi * !Rayon! ** 3
Calculer la valeur minimum entre plusieurs champs
Expression:
min([!Champ1!,!Champ2!,!Champ3!,!Champ4!])
Calculer la valeur maximum entre plusieurs champs
Expression:
max([!Champ1!,!Champ2!,!Champ3!,!Champ4!])
Calculer la somme des valeurs entre plusieurs champs
Expression:
sum([!Champ1!,!Champ2!,!Champ3!,!Champ4!])
Calculer la moyenne des valeurs entre plusieurs champs
Expression:
avg([!Champ1!,!Champ2!,!Champ3!,!Champ4!])
Incrémenter une valeur enregistrement après enregistrement, à partir d'une valeur de départ et d'un intervalle (ici on part de 0 avec un pas de 3):
Bloc de code:
rec='first'
def autoIncrement(start,step):
global rec
if (rec=='first'):
rec = start
else:
rec = rec + step
return rec
Expression:
autoIncrement(0,3)
Accumuler les valeurs d'un champ, enregistrement après enregistrement. La valeur du dernier enregistrement correspond à la somme de toutes les valeurs de ce champs:
Bloc de code:
total = 0
def accumulate(increment):
global total
if total:
total += increment
else:
total = increment
return total
Expression:
accumulate(!Mon_Champ_Num!)
Expressions sur les dates
Calculer la date courante:
Expression:
time.strftime("%d/%m/%Y")
Calculer la date et l'heure courante:
Expression:
datetime.datetime.now()
Insérer une date spécifique (ici le 5 décembre 2015)::
Expression:
datetime.datetime(2015, 12, 5)
Calculer le nombre de jours compris entre la date actuelle et la date d'un champ:
Expression:
(datetime.datetime.now() - arcpy.time.ParseDateTimeString(!Mon_Champ_Date!)).days
Calculer le nombre de secondes compris entre la date actuelle et la date d'un champ:
Expression:
(datetime.datetime.now() - arcpy.time.ParseDateTimeString(!Mon_Champ_Date!)).seconds
Calculer une date en ajoutant 3 semaines à la date d'un champ:
Expression:
arcpy.time.ParseDateTimeString(!Mon_Champ_Date!) + datetime.timedelta(weeks=3)
Calculer une date en ajoutant 10 jours à la date d'un champ:
Expression:
arcpy.time.ParseDateTimeString(!Mon_Champ_Date!) + datetime.timedelta(days=10)
Calculer une date en ajoutant 12 heures à la date d'un champ:
Expression:
arcpy.time.ParseDateTimeString(!Mon_Champ_Date!) + datetime.timedelta(hours=12)
Calculer le jour de la semaine (par exemple: lundi) de la date d'un champ:
Expression:
arcpy.time.ParseDateTimeString( !Mon_Champ_Date! ).strftime('%A')
Calculer une date à partir d'un champ contenant des
timestamps:
Bloc de code:
from datetime import datetime
Expression:
datetime.utcfromtimestamp(!Mon_Champ_Timestamp!)
Calculer des
timestamps à partir d'un champ contenant des dates:
Bloc de code:
import calendar
def convertToTimestamp(value):
dt= arcpy.time.ParseDateTimeString(value)
return calendar.timegm(dt.utctimetuple())
Expression:
convertToTimestamp(!Mon_Champ_Date!)
Expressions sur les géométries
Calculer le X du centroïde des géométries des entités:
Expression:
!shape.centroid.x!
Calculer le Y du centroïde des géométries des entités:
Expression:
!shape.centroid.y!
Calculer le Z du centroïde des géométries des entités:
Expression:
!shape.centroid.z!
Calculer le X du barycentre des géométries des entités:
Expression:
!shape.truecentroid.x!
Calculer le X du point d'étiquetage des géométries des entités:
Expression:
!shape.labelpoint.x!
Calculer le périmètre des polygones ou la longueur des polylignes dans les unités de la couche:
Expression:
!shape.length!
Calculer le périmètre des polygonesZ ou la longueur des polylignesZ en prenant en compte le Z des sommets:
Expression:
!shape.length3D!
Calculer le périmètre des polygones ou la longueur des polylignes dans les unités de votre choix (ici en kilomètres):
Expression:
!shape.length@kilometers!
Calculer la superficie des polygones dans les unités de la couche:
Expression:
!shape.area!
Calculer la superficie des polygones dans les unités de votre choix (ici en km2):
Expression:
!shape.area@squarekilometers!
Calculer la superficie des polygones dans les unités de votre choix (ici en hectares):
Expression:
!shape.area@hectares!
Calculer le X du premier sommet des polylignes ou des polygones:
Expression:
!shape.firstpoint.x!
Calculer le X du dernier sommet des polylignes ou des polygones (dans le cas de polygone mono-partie, le premier et le dernier sommet sont les mêmes):
Expression:
!shape.lastpoint.x!
Calculer le X du coin inférieur-gauche de l'enveloppe des polylignes ou des polygones:
Expression:
!shape.extent.xmin!
Calculer le Y du coin inférieur-gauche de l'enveloppe des polylignes ou des polygones:
Expression:
!shape.extent.ymin!
Calculer la largeur de l'enveloppe des polylignes ou des polygones:
Expression:
!shape.extent.width!
Calculer la hauteur de l'enveloppe des polylignes ou des polygones:
Expression:
!shape.extent.height!
Calculer le nombre de parties composant la géométrie des entités:
Expression:
!shape.partcount!
Calculer le nombre de sommets composant la géométrie des entités:
Expression:
!shape.pointcount!
Calculer le Z moyen des sommets de polylignesZ, de polygonesZ ou de multipatch:
Bloc de code:
def AverageZ(feat):
avg=0
partnum = 0
partcount = feat.partCount
pntcount = 0
while partnum < partcount:
part = feat.getPart(partnum)
pnt = part.next()
while pnt:
pntcount += 1
if pnt:
avg=avg + pnt.z
pnt = part.next()
partnum += 1
return avg/pntcount
Expression:
AverageZ(!shape!)
Calculer le Z minimum des sommets de polylignesZ, de polygonesZ ou de multipatch:
Bloc de code:
def MinimumZ(feat):
min=0
partnum = 0
partcount = feat.partCount
pntcount = 0
while partnum < partcount:
part = feat.getPart(partnum)
pnt = part.next()
min=pnt.z
while pnt:
pntcount += 1
if pnt:
if (pnt.z < min):
min=pnt.z
pnt = part.next()
partnum += 1
return min
Expression:
MinimumZ(!shape!)
Calculer le Z maximum des sommets de polylignesZ, de polygonesZ ou de multipatch:
Bloc de code:
def MaximumZ(feat):
max=0
partnum = 0
partcount = feat.partCount
pntcount = 0
while partnum < partcount:
part = feat.getPart(partnum)
pnt = part.next()
max=pnt.z
while pnt:
pntcount += 1
if pnt:
if (pnt.z > max):
max=pnt.z
pnt = part.next()
partnum += 1
return max
Expression:
MaximumZ(!shape!)
Calculer le M moyen des sommets de polylignesM ou de polygonesM:
Bloc de code:
def AverageM(feat):
avg=0
partnum = 0
partcount = feat.partCount
pntcount = 0
while partnum < partcount:
part = feat.getPart(partnum)
pnt = part.next()
while pnt:
pntcount += 1
if pnt:
avg=avg + pnt.m
pnt = part.next()
partnum += 1
return avg/pntcount
Expression:
AverageM(!shape!)
Mettre à jour la géométrie des points de la couche à l'aide de deux champs X et Y
(expression à appliquer sur le champ "shape"):
Expression:
arcpy.Point(!Champ_X!,!Champ_Y!)
Déplacer les points d'une couche d'une distance de 1000 unités X et 500 unités en Y:
Bloc de code:
def Move(feat,deltaX,deltaY):
newfeat = arcpy.Point(feat.centroid.X + deltaX ,feat.centroid.Y + deltaY)
return newfeat
Expression:
Move(!shape!,1000,500)
Autres expressions de calcul
Mettre les valeurs d'un champ à "Null":
Expression:
None
Construire une chaîne à partir des valeurs de différents champs:
Expression:
"{}:{}".format(!Champ_Heures!, !Champ_Minutes!)
Construire une chaîne en forçant l'écriture du signe + ou - devant une valeur numérique:
Expression:
'{:+d}'.format(!Champ_Num!)
Construire une chaîne en mettant les "0" nécessaires à gauche de la valeur numérique (ici un exemple où on force le nombre à faire 4 caractères, par exemple pour 82 on obtiendra la chaîne "0082":
Expression:
'{:04d}'.format(!Champ_Num!)
Construire une chaîne à partir d'une date selon le format souhaité:
Expression:
'{:%d-%m-%Y %H:%M}'.format(arcpy.time.ParseDateTimeString(!Champ_Date!))