Utilisation d'arcgis desktop 10.3.1 J'ai un script qui utilise un curseur de recherche pour ajouter des valeurs à une liste, puis utilise min () pour trouver le plus petit entier. La variable est ensuite utilisée dans un script. La classe d'entités comporte 200 000 lignes et le script prend beaucoup de temps. Y a-t-il un moyen de le faire plus rapidement? Pour le moment, je pense que je le ferais à la main plutôt que d'écrire un script en raison du temps qu'il faut.
import arcpy
fc = arcpy.env.workspace = arcpy.GetParameterAsText(0)
Xfield = "XKoordInt"
cursor = arcpy.SearchCursor(fc)
ListVal = []
for row in cursor:
ListVal.append(row.getValue(Xfield))
value = min(ListVal)-20
print value
expression = "(!XKoordInt!-{0})/20".format(value)
arcpy.CalculateField_management (fc, "Matrix_Z" ,expression, "PYTHON")
arcpy.Statistics_analysis
? desktop.arcgis.com/en/arcmap/10.3/tools/analysis-toolbox/…min_val = min([i[0] for i in arcpy.da.SearchCursor(fc,Xfield)])
Réponses:
Je peux voir plusieurs choses qui peuvent ralentir votre script. La chose qui est probablement très lente est la
arcpy.CalculateField_management()
fonction. Vous devez utiliser un curseur, il sera plus rapide de plusieurs magnitudes. De plus, vous avez dit que vous utilisez ArcGIS Desktop 10.3.1, mais que vous utilisez les anciens curseurs de style ArcGIS 10.0, qui sont également beaucoup plus lents.L'opération min () même sur une liste de 200K sera assez rapide. Vous pouvez le vérifier en exécutant ce petit extrait; cela se passe en un clin d'œil:
Voyez si c'est plus rapide:
ÉDITER:
J'ai effectué des tests de synchronisation et, comme je le soupçonnais, la calculatrice de terrain a pris presque deux fois plus de temps que le nouveau curseur de style. Fait intéressant, le curseur à l'ancienne était ~ 3 fois plus lent que la calculatrice de terrain. J'ai créé 200 000 points aléatoires et utilisé les mêmes noms de champs.
Une fonction décoratrice a été utilisée pour chronométrer chaque fonction (il peut y avoir une légère surcharge dans la configuration et le démontage des fonctions, donc peut-être que le module timeit serait un peu plus précis pour tester les extraits).
Voici les résultats:
Et voici le code que j'ai utilisé (tout décomposé en fonctions individuelles pour utiliser le
timeit
décorateur):Et enfin, c'est ce que l'impression réelle était de ma console.
Edit 2: Je viens de publier des tests mis à jour, j'ai trouvé un léger défaut avec ma
timeit
fonction.la source
"XKoordInt"
. Voir mon montage, tout ce que vous avez à faire est de sauter les null.range
. ArcGIS utilise toujours Python 2.7, il renvoie donc alist
. Mais dans 3.x,range
c'est son propre type spécial d'objet qui peut avoir des optimisations. Un test plus fiable seraitmin(list(range(200000)))
, ce qui garantirait que vous travaillez avec une liste simple. Pensez également à utiliser letimeit
module pour les tests de performances.Comme le souligne @crmackey, la partie lente est probablement due à la méthode de calcul du champ. Comme alternative aux autres solutions appropriées, et en supposant que vous utilisez une géodatabase pour stocker vos données, vous pouvez utiliser la commande Trier par sql pour trier par ordre croissant avant d'effectuer le curseur de mise à jour.
Dans ce cas, la clause where supprime les valeurs NULL avant d'effectuer la requête, ou vous pouvez utiliser l'autre exemple qui vérifie Aucun avant la mise à jour.
la source
min()
. Je vais également inclure cela dans mes tests de vitesse pour montrer le gain de performances.0.56
quelques secondes, ce qui n'est pas autant un gain de performances que je l'aurais prévu.Vous pouvez également utiliser numpy dans des cas comme celui-ci, bien qu'il soit plus gourmand en mémoire.
Vous obtiendrez toujours un goulot d'étranglement lors du chargement des données dans un tableau numpy, puis à nouveau dans la source de données, mais j'ai constaté que la différence de performances est meilleure (en faveur de numpy) avec des sources de données plus importantes, surtout si vous avez besoin de plusieurs statistiques / calculs .:
la source
Pourquoi ne pas trier le tableau par ordre croissant, puis utiliser un curseur de recherche pour saisir la valeur de la première ligne? http://pro.arcgis.com/en/pro-app/tool-reference/data-management/sort.htm
la source
Je voudrais envelopper l' expression
SearchCursor
dans un générateur (c.-à-d.min()
) Pour la vitesse et la concision. Incorporez ensuite la valeur minimale de l'expression du générateur dans unda
typeUpdateCursor
. Quelque chose comme ceci:la source
SearchCursor
être fermé lorsque vous en avez terminé?Dans votre boucle, vous avez deux références de fonction qui sont réévaluées pour chaque itération.
for row in cursor: ListVal.append(row.getValue(Xfield))
Il devrait être plus rapide (mais un peu plus complexe) d'avoir les références en dehors de la boucle:
la source
append()
méthode intégrée dulist
type de données. Je ne pense pas que c'est là que son goulot d'étranglement se produit, je parierais que la fonction de calcul sur le terrain est le coupable. Cela peut être vérifié en synchronisant la calculatrice de champ avec un nouveau curseur de style.