Suite

Mélanger aléatoirement les valeurs d'une colonne dans une série de nouvelles colonnes dans une classe d'entités dans ArcGIS for Desktop ?


J'essaie d'exécuter une simulation Monte Carlo sur une classe d'entités ponctuelles. Pour ce faire, j'essaie de prendre les valeurs d'une colonne de données observées et de les "mélanger" au hasard entre les points sur n colonnes "simulées" supplémentaires. Dans mon cas, j'aimerais ajouter 199 nouvelles colonnes, chacune avec les valeurs des données observées redistribuées de manière aléatoire entre les points.

Mes données observées sont binaires (1 et 0)

J'ai déjà pu le faire dans R et ramener la table dans ArcGIS, mais les tables sont devenues si lourdes que j'ai des difficultés à les ramener dans ArcGIS et j'aimerais exécuter l'analyse dans ArcGIS, plutôt que de déménager et dehors.

Est-ce que quelqu'un a une idée de comment faire cela? J'ai essayé d'utiliser le curseur, mais j'ai échoué.


Vous pouvez accomplir cette tâche à l'aide du workflow suivant :

Générer une liste de toutes les valeurs (1 et 0) dans un champ

vals = [row[0] pour la ligne dans arcpy.da.SearchCursor(fc, ["binary"])]

Créez une boucle égale au nombre de champs que vous souhaitez créer

pour x dans la plage(2) :

Dans cette boucle, mélangez aléatoirement la liste des 1 et des 0

aléatoire.shuffle(vals)

Incorporer la valeur de la plage dans le nom du champ

fieldName = "Champ" + str((x + 1))

Démarrez un UpdateCursor pour mettre à jour le champ dans la plage x

avec arcpy.da.UpdateCursor(fc, fieldName) comme curseur :

Peut-être le plus important, créez un compteur et utilisez-le pour indexer la liste mélangée. Ajouter cette valeur indexée à la table attributaire

row[0] = int(vals[count])

import arcpy, os, random # Votre classe d'entités en entrée fc = r'C:path	ofeatureclass' # Obtenez une liste de toutes les valeurs (c'est-à-dire 1 et 0) dans le champ appelé "binaire" vals = [row[ 0] pour la ligne dans arcpy.da.SearchCursor(fc, ["binary"])] # Dans votre cas, vous voudrez probablement changer la plage en 199 pour x dans range(2) : random.shuffle(vals) #Randomly liste aléatoire fieldName = "Field" + str((x + 1)) arcpy.AddField_management(fc, fieldName, "SHORT") count = 0 avec arcpy.da.UpdateCursor(fc, fieldName) comme curseur : pour la ligne dans le curseur : row[0] = int(vals[count]) count = count + 1 cursor.updateRow(row) del count

Voici quelque chose que j'ai mis en place, il fonctionne à peu près de la même manière que le script d'Aaron.

import sys, os, arcpy, random InFC = sys.argv[1] ThresholdOfOnes = 50 # pour cent c'est-à-dire ! Columns = 199 ColRange = range(1,Columns + 1) InCount = int(arcpy.GetCount_management(InFC).getOutput(0)) ThresholdOfOnes = (InCount * ThresholdOfOnes) / 100 # convertir le pourcentage en nombre OIDlist = list() desc = arcpy.Describe(InFC) OIDfield = desc.OIDFieldName # récupère les OID dans une liste avec arcpy.da.SearchCursor(InFC,OIDfield) comme srch : pour la ligne dans srch : OIDlist.append(row[0]) pour ColNum dans ColRange : FieldName = "Col_%d" % ColNum SelOIDlist = list() tandis que len(SelOIDlist) < ThresholdOfOnes : PosIndex = random.randint(0,len(OIDlist)) # choisissez un nombre aléatoire si OIDlist[PosIndex] n'est pas dans SelOIDlist : # si l'OID n'est pas déjà dans la liste SelOIDlist.append(OIDlist[PosIndex]) # maintenant à sélectionner avec l'oidlist # commencez à construire une requête de définition DefQ = "%s in (" % OIDfield isFirst = True pour ThisOID in SelOIDlist : if isFirst : # le premier n'a pas de virgule DefQ = DefQ + str(ThisOID) isFirst = False else : DefQ = DefQ + "," + str(ThisOID) DefQ = DefQ + ")" # ferme le crochet # ajouter le champ s'il n'existe pas fList = arcpy.ListFields(InFC,FieldName) sinon fList: arcpy.AddField_management(InFC,FieldName,"SHORT") # vider le champ arcpy.CalculateField_management(InFC,FieldName,"0","PYTHON ") # démarrer un curseur avec uniquement les fonctionnalités aléatoires avec arcpy.da.UpdateCursor(InFC,FieldName,DefQ) comme UpCur : pour UpRow dans UpCur : UpRow[0] = 1 # définir la valeur UpCur.updateRow(UpRow) # stocker il

Cela fonctionnera pour les fichiers de formes ou les classes d'entités dans les bases de données… il obtient une liste des oids, puis choisit au hasard dans la liste (en garantissant aucune duplication) jusqu'à ce que le seuil soit atteint, puis transforme la liste en une requête de définition et met à jour les fonctionnalités. En cours de route, si le champ n'existe pas, il l'ajoutera, garantissant que les valeurs précédentes sont écrasées.


Un dictionnaire sophistiqué et un curseur de mise à jour en un seul passage seraient les plus rapides/meilleurs, mais quelque chose comme ça fonctionnerait aussi :

import arcpy, random pntFC = r"C:	emp	est.gdb	est_pnts" boolField = "ORIG_TRUTH" #original bool field falseOidList = [r[0] for r in arcpy.da.SearchCursor(pntFC, ["[email protected] "], boolField + " = 0")] trueOidList = [r[0] pour r dans arcpy.da.SearchCursor(pntFC, ["[email protected]"], boolField + " = 1")] falseCount = len(falseOidList) trueCount = len(trueOidList) pour i dans la plage (1 199 + 1) : randomFieldName = "RND_" + str(i) arcpy.AddField_management(randomFieldName, "SHORT") randomTrueOids = random.sample(falseOidList + trueOidList, trueCount) arcpy. MakeFeatureLayer_management(pntFC, "fl", "OID dans (" + ",".join(str(oid) pour oid dans (falseOidList + trueOidList)) + ")" arcpy.CalculateField_management("fl", randomFieldName, "1" , "PYTHON") arcpy.MakeFeatureLayer_management(pntFC, "fl", randomFieldName + " IS NULL") arcpy.CalculateField_management("fl", randomFieldName, "0", "PYTHON")


Voir la vidéo: Gas burner. burner how to make (Octobre 2021).