J'ai une classe d'entités ponctuelles assez importante dans une géodatabase fichier (~ 4 000 000 d'enregistrements). Il s'agit d'une grille de points régulière avec une résolution de 100 m.
J'ai besoin d'effectuer une sorte de généralisation sur cette couche. Pour cela, je crée une nouvelle grille où chaque point se situe au milieu de 4 "anciens" points:
* * * *
o o o
* * * *
o o o
* * * *
[*] = point de la grille d'origine - [o] = point de la nouvelle grille
La valeur d'attribut de chaque nouveau point est calculée sur la base des valeurs pondérées de ses 4 voisins dans l'ancienne grille. Je boucle donc sur tous les points de ma nouvelle grille et, pour chacun d'eux, je boucle sur tous les points de mon ancienne grille, afin de trouver les voisins (en comparant les valeurs de X et Y dans la table attributaire). Une fois que 4 voisins ont été trouvés, nous sortons de la boucle.
Il n'y a pas de complexité méthodologique ici mais mon problème est que, sur la base de mes premiers tests, ce script va durer des semaines ...
Voyez-vous une possibilité de le rendre plus efficace? Quelques idées sur le dessus de ma tête:
- Indexez les champs X et Y => Je l'ai fait mais je n'ai pas remarqué de changement de performance significatif
- Effectuez une requête spatiale pour trouver les voisins plutôt que basée sur un attribut. Cela aiderait-il réellement? Quelle fonction spatiale dans ArcGIS devrait faire le travail? Je doute que, par exemple, la mise en mémoire tampon de chaque nouveau point se révélera plus efficace
- Transformez la classe d'entités en tableau NumPy. Est-ce que cela aiderait? Je n'ai pas beaucoup travaillé avec NumPy jusqu'à présent et je ne voudrais pas m'y plonger à moins que quelqu'un ne me dise que cela pourrait vraiment aider à réduire le temps de traitement
- Rien d'autre?
la source
Réponses:
Et si vous introduisiez les points dans un tableau numpy et utilisiez un cKDTree scipy pour rechercher des voisins. Je traite des nuages de points LiDAR avec un grand nombre de points (> 20 millions) en plusieurs MINUTES en utilisant cette technique. Il y a de la documentation ici pour kdtree et ici pour la conversion numpy. Fondamentalement, vous lisez les x, y dans un tableau et parcourez chaque point du tableau en trouvant des indices de points à une certaine distance (voisinage) de chaque point. Vous pouvez utiliser ces indices pour calculer ensuite d'autres attributs.
la source
Je suis avec Barbarossa ... les curseurs arcpy sont incroyablement boiteux, donc je ne les utilise que pour parcourir une table ou une classe d'entités exactement une fois. Si je ne peux pas faire le travail en un seul cycle, j'utilise le curseur pour remplir un autre type de structure de données et travailler avec cela.
Si vous ne voulez pas vous soucier de numpy, créez simplement un dictionnaire python simple où vous utilisez vos coordonnées comme une simple clé de texte et remplissez les attributs dont vous avez besoin pour le calcul dans une liste en tant que valeur de l'élément de dictionnaire.
Dans une deuxième étape, vous pouvez facilement obtenir les valeurs dont vous avez besoin pour calculer un point en les obtenant simplement à partir de votre dictionnaire (ce qui est incroyablement rapide, en raison de l'inexistence des dictionnaires dans les éléments).
la source
Pour une grille régulière, il devrait être de loin plus efficace de travailler dans un format raster. Convertissez votre première grille en un raster, vous pouvez rééchantillonner à la même résolution en utilisant un interpolateur bilinéaire mais en décalant votre image de sortie de 1/2 pixel en X et Y, et de nouveau en points si vous avez encore besoin de points.
EDIT: pour les règles de décisions complexes, vous pouvez convertir chacun des champs dont vous avez besoin en une nouvelle bande raster, puis vous faites quatre copies de ces bandes et vous décalez votre raster dans les 4 directions de 1/2 pixel (+50, - 50), (+ 50, + 50), (-50, -50) et (-50, + 50). Ensuite, vous pouvez utiliser l'algèbre de carte régulière
la source
Merci à tous pour votre aide!
J'ai finalement trouvé un moyen très non-pythonique pour résoudre ce problème ... Ce qui prenait en fait le plus de temps de calcul était de trouver les 4 voisins de chaque point. Plutôt que d'utiliser les attributs X et Y (soit avec un curseur arcpy, soit dans une autre structure de données, comme un ditionnaire python), j'ai fini par utiliser l'outil ArcGIS Generate near table . Je suppose que cela profite des index spatiaux et les performances sont évidemment beaucoup plus élevées, sans que je doive implémenter l'index moi-même.
la source
Le problème avec les curseurs est que vous ne pouvez les parcourir que d'une seule manière et que vous ne pouvez pas revenir en arrière. Bien que cela ne soit pas recommandé, vous pouvez remplir les feautres dans une structure si vous prévoyez de les revoir.
Si vous pouviez traiter vos fonctionnalités en une seule boucle, je vous suggère d'activer le recyclage. C'est un paramètre de votre fonction de recherche de fonctionnalités qui permet à python de réutiliser la mémoire allouée par les anciennes fonctionnalités et de rendre la traversée des fonctionnalités dans un curseur beaucoup plus rapide. Vous pouvez traiter votre grille 80% plus rapidement.
Le problème est que vous ne pouvez pas activer le recyclage si vous envisagez de stocker les fonctionnalités récupérées à partir d'un curseur.
la source