Il y a quelque temps, j'ai écrit une fonction Python rapide pour convertir une table d'attributs en un dictionnaire Python, où la clé est extraite d'un champ ID unique spécifié par l'utilisateur (généralement le champ OID). De plus, par défaut, tous les champs sont copiés dans le dictionnaire, mais j'ai inclus un paramètre permettant de spécifier uniquement un sous-ensemble.
def make_attribute_dict(fc, key_field, attr_list=['*']):
dict = {}
fc_field_objects = arcpy.ListFields(fc)
fc_fields = [field.name for field in fc_field_objects if field.type != 'Geometry']
if attr_list == ['*']:
valid_fields = fc_fields
else:
valid_fields = [field for field in attr_list if field in fc_fields]
if key_field not in valid_fields:
cursor_fields = valid_fields + [key_field]
else:
cursor_fields = valid_fields
with arcpy.da.SearchCursor(fc, cursor_fields) as cursor:
for row in cursor:
key = row[cursor_fields.index(key_field)]
subdict = {}
for field in valid_fields:
subdict[field] = row[cursor_fields.index(field)]
dict[key] = subdict
del subdict
return dict
Cela fonctionne très bien pour des ensembles de données relativement petits, mais je viens de l'exécuter sur une table contenant environ 750 000 lignes et 15 champs - environ 100 Mo dans une géodatabase fichier. Sur ceux-ci, la fonction s'exécute beaucoup plus lentement que ce à quoi je m'attendais: environ 5-6 minutes (et c'est après avoir copié la table dans l' in_memory
espace de travail). J'aimerais vraiment trouver un moyen d'accélérer la conversion en dictionnaire, ou obtenir un aperçu d'une meilleure stratégie pour manipuler de grandes quantités de données d'attributs à l'aide de Python.
UpdateCursors ne fonctionnera pas bien pour moi, car lorsqu'une ligne change, elle a le potentiel de déclencher des changements dans plusieurs autres. Les parcourir et les traiter un par un est trop lourd pour ce dont j'ai besoin.
la source
subdict = {}
partdel subdict
donne un temps de traitement d'environ 10 secondes.subdict[field] = row[cursor_fields.index(field)]
est plus rapide que l'appelsubdict[field] = row.getValue(field)
. Dans ce dernier scénario, vous effectuez une étape ... bien que la différence de performances entre l'indexation de deux listes (cursor_fields
etrow
) et l'utilisation d'un seul processus ESRI ne soit pas beaucoup mieux et pourrait même être pire!Réponses:
Je pense que le problème est probablement vos deux lignes où vous allez sur les champs et ajoutez chaque champ individuellement à votre
subdict
dictionnaire.Votre
row
objet est déjà un tuple dans le même ordre que vos champs, profitez-en et utilisez lazip
fonction.Cela a traversé une classe d'entités de géodatabase fichier de champ record de 218k en 8 secondes sur mon système.
Edit: J'ai essayé un test plus rigoureux. 518k enregistrements sur une connexion SDE distante avec 16 champs, dont OBJECTID et Shape, exécutés en 32 bits. 11 secondes :)
la source
key_field
le premier champ afin de pouvoir compter sur l'utilisationrow[0]
pour référencer la valeur dekey_field
. J'ai également dû changer votre variabledict
enattdict
. dict est un mot-clé, et sans ce mot-clé je ne pourrais pas utiliserdict(zip())
arcpy.da
est censé permettre.