Bienvenue! Inscrivez-vous et rejoignez notre communauté :)
  • Login:

Bienvenue sur Forum SIG - Systèmes d'Information Géographique et Géomatique.

Bienvenue sur le forumSIG. S'il s'agit de votre première visite, assurez vous de faire une recherche préalable dans les FAQ SIG. Vous devez vous inscrire avant de pouvoir poster.

Affichage des résultats 1 à 13 sur 13
  1. #1

    Date d'inscription
    novembre 2013
    Localisation
    Genève
    Emploi
    Chargé de... travail...
    Messages
    53

    Par défaut [PYTHON] Boucle sur les valeurs uniques d'un champ

    Bonjour,

    Ca paraît tout simple, mais j'ai un mal fou à trouver des exemples de boucles sur les valeurs uniques d'un champ.

    Dans mon cas, je souhaite faire des opérations sur une les d'observations d'une même espèce (= points avec un même attribut) dans une sélection d'observations ayant un champ de précision > x mètres.

    J'ai donc commencé par faire ma première sélection :
    Code:
    maklay = arcpy.MakeFeatureLayer_management(geif, "laygeif")
    np = arcpy.SelectLayerByAttribute_management(maklay, "NEW_SELECTION", '"XY_PRECISION">250')
    Ca joue.

    Maintenant, je veux initier une boucle while contenant une boucle for sur ma première sélection.

    Il faudrait quelque chose du genre :

    Code:
    While (condition tordue et trop longue pour mettre ici)
           for chaque espèce in np :
               arcpy.selec...
    J'ai pensé à quelque chose dans l'idée de ListFeatureClass mais sur les attributs d'un champ, mais je cale...

    Pourriez-vous m'indiquer au moins une piste svp?

    Merci d'avance!

  2. #2
    Quasi-modo Supporter(rice)

    Date d'inscription
    octobre 2008
    Messages
    998

    Par défaut Re : [PYTHON] Boucle sur les valeurs uniques d'un champ

    Bonjour,
    Personnellement, je me sers d'un curseur pour récupérer mes valeurs de champs dans une liste puis j'en fais un un set (supprime les doublons)
    ensuite pour chaque valeur du set, je recrée un curseur ou une sélection avec la whereclause qui va bien !

    Aller je fais un peu de virtual code :
    Code:
    maliste = []
    with arcpy.da.SearchCursor(maclasse, [monchamp], whereclauseinitiale) as scur:
       for r in scur:
          maliste.append(r[0])
    monset = set(maliste)
    
    for elem in monset:
       with arcpy.da.SearchCursor(maclasse, [monchamp], manouvellewhereclauseavecelemdedans) as scur:
          for r in scur:
              FAISDESTRUCS !
    
    ou
    
    for elem in monset:
       arcpy.MakeFeautureLayer(...)
    "Les sigé, c'est la balle !"
    Joey StarApic et Kool Shape du groupe MNT
    Album: Laisse pas trainer ton TIN

  3. #3

    Date d'inscription
    novembre 2013
    Localisation
    Genève
    Emploi
    Chargé de... travail...
    Messages
    53

    Par défaut Re : [PYTHON] Boucle sur les valeurs uniques d'un champ

    Merci Speed-Popeye.

    Vu comme ça, c'est simple en fait... Du coup je comprends un peu mieux ce bon vieux Pyth! (J'aurais du prendre Mac comme pseudo... ).

    Allé, tatatatata taaaaaa ta ta taaa ta ta taaa tata tata...

  4. #4

    Date d'inscription
    novembre 2013
    Localisation
    Genève
    Emploi
    Chargé de... travail...
    Messages
    53

    Par défaut Re : [PYTHON] Boucle sur les valeurs uniques d'un champ

    Bah, ça passe, mais je n'arrive pas à obtenir ce que j'attendais.

    Je veux donc :

    • pour chaque valeur unique d'un champ "conc" (concrètement, un numéro d'espèce de plante concaténé avec un numéro de pas de temps d'observation),
      • pour chaque ligne dans cet ensemble de lignes ayant une même valeur "conc"
        • qu'une couche dissbuff (buffers) sélectionne par localité une couche buff (autres buffers)
        • compter le nombre d'entités sélectionnées
        • écrire ce nombre dans une colonne pour contrôle
        • si ce nombre est > 0,
          • inscrire 1 dans une colonne

        • sinon,
          • y inscrire 0

    Or, toutes les entités buff intersectées par une entité dissbuff sont sélectionnées au lieu de seulement celles d'une valeur unique "conc".

    Il y a donc un bug dans ma liste ou dans ma boucle, mais tel l'escargot dans une boîte de talc... je sèche.

    Voici le script :

    Code:
    # Import arcpy module
    import arcpy
    # Chemins des toolboxes
    #arcpy.AddToolbox("C:\\Program Files (x86)\\ArcGIS\Desktop10.2\\ArcToolbox\\Toolboxes\\Data Management Tools.tbx")
    arcpy.env.overwriteOutput = True
    
    
    # Environnement de travail et variables représentant la gdb.
    wsp = arcpy.env.Workspace = arcpy.GetParameterAsText(0) #Dataset
    
    
    
    # Variables
        
    buff = arcpy.GetParameterAsText(1) #Fichier BUFFER brut
    dissbuff = arcpy.GetParameterAsText(2) #buffers < 50m fusionnés
    #prec = arcpy.GetParameterAsText(3) # Champ précision
    eli = "Elim" #Champ elimination des notes
    ctrl = "ctrl"
    conc = "conc"
    sp = "NO_NOM_IF"
    pt = "PAS_TPS"
    #temp = "uptemp"
    maklay = arcpy.MakeFeatureLayer_management(buff, "maklay") #Passer buffer en layer
    makldis = arcpy.MakeFeatureLayer_management(dissbuff, "makldis")
    np = arcpy.SelectLayerByAttribute_management(maklay, "NEW_SELECTION", "XY_PRECISION_ORIGINAL > 50") #Selectionner les observations >50m de précision (elles seront découpées par les plus précises)
    
    #Boucle d'élimination des notes trop peu précises proches de notes plus précises par espèces et par pas de temps
    
         #Ajouter un champ 0/1 signalant les observations retenues ou non
    
    elim = arcpy.AddField_management(buff, eli, "SHORT")
    ctrl = arcpy.AddField_management(buff, ctrl, "SHORT")
    malistecc = []
    with arcpy.da.SearchCursor(np, "conc") as scur:
         for r in scur:
              malistecc.append(r[0])
    monsetcc = set(malistecc)
    for elemts in monsetcc:
         flds = ["ctrl", "Elim"]
         with arcpy.da.UpdateCursor(buff, flds) as cursor:
              for row in cursor:          
                   a  = arcpy.SelectLayerByLocation_management (np, "INTERSECT", makldis)
                   b  = int(arcpy.GetCount_management(a).getOutput(0))
                   row[0] = b
                   if b > 0 :
                        row[1] = 1
                   else:
                        row[1] = 0
                   cursor.updateRow(row)

  5. #5
    Quasi-modo Supporter(rice)

    Date d'inscription
    octobre 2008
    Messages
    998

    Par défaut Re : [PYTHON] Boucle sur les valeurs uniques d'un champ

    En effet il te manque une étape.
    Si j'ai bien compris pour chaque elemts (d'ailleurs je sortirai le "s" car elemts contient un seul élément de monsetcc) il faut que tu sélectionnes le sous ensemble avec la valeur de elem.
    Or je ne vois pas cette étape dans ton code.
    Tu n'utilises pas la valeur de elemts.

    avant ton a = arcpy.SelectLayerByLocation_management (np, "INTERSECT", makldis), j'aurais fait une nouvelle layer de np (la première servant uniquement à faire la liste)

    si je ne m'embrouille pas, un truc du genre : np = = arcpy.SelectLayerByAttribute_management(maklay, "NEW_SELECTION", "XY_PRECISION_ORIGINAL > 50 AND MONCHAMP = " + elemts) juste avant le a =
    "Les sigé, c'est la balle !"
    Joey StarApic et Kool Shape du groupe MNT
    Album: Laisse pas trainer ton TIN

  6. #6

    Date d'inscription
    novembre 2013
    Localisation
    Genève
    Emploi
    Chargé de... travail...
    Messages
    53

    Par défaut Re : [PYTHON] Boucle sur les valeurs uniques d'un champ

    Yep, j'essaie.

    J'ai eu la même idée... à 3h du mat, mais. Ta réponse m'aide à formaliser la chose!

    Merci.

  7. #7

    Date d'inscription
    novembre 2013
    Localisation
    Genève
    Emploi
    Chargé de... travail...
    Messages
    53

    Par défaut Re : [PYTHON] Boucle sur les valeurs uniques d'un champ

    Après 3h d'essais, j'en suis arrivé à ça :

    Code:
    malistecc = []
    with arcpy.da.SearchCursor(np, "STRCONC") as scur:
         for r in scur:
              malistecc.append(r[0])
    monsetcc = set(malistecc)
    for elemt in monsetcc:
         np2 = arcpy.SelectLayerByAttribute_management(maklay, "NEW_SELECTION",  "STRCONC ="  + "'" + elemt + "'")
         ndiss = arcpy.SelectLayerByAttribute_management(makldis, "NEW_SELECTION", "STRCONC ="  + "'" + elemt + "'")
         for row in elemt :          
              a  = arcpy.SelectLayerByLocation_management (np2, "INTERSECT", ndiss)
              b  = int(arcpy.GetCount_management(a).getOutput(0))
              flds = ["ctrl", "Elim"]
              with arcpy.da.UpdateCursor(buff, flds) as cursor:
                   for row in cursor:             
                        row[0] = b
                        if b > 0 :
                             row[1] = 1
                        else:
                             row[1] = 0
                        cursor.updateRow(row)
    J'ai du faire une liste sur un champ texte pour la première boucle pour contourner l'erreur "int is not iterable" et placé les opérations de sélection juste après l'itération sur les ligne de mon ensemble d'éléments, ce qui a fait passer le temps de procédure du script de 3 min env. à quelques secondes :

    Avant :

    Code:
    for elemt in monsetcc:
         np2 = arcpy.SelectLayerByAttribute_management(maklay, "NEW_SELECTION",  "STRCONC ="  + "'" + elemt + "'")
         ndiss = arcpy.SelectLayerByAttribute_management(makldis, "NEW_SELECTION", "STRCONC ="  + "'" + elemt + "'")
         for row in elemt :          
              a  = arcpy.SelectLayerByLocation_management (np2, "INTERSECT", ndiss)
              b  = int(arcpy.GetCount_management(a).getOutput(0))
              flds = ["ctrl", "Elim"]
              with arcpy.da.UpdateCursor(buff, flds) as cursor:
                   np2 = arcpy.SelectLayerByAttribute_management(maklay, "NEW_SELECTION",  "STRCONC ="  + "'" + elemt + "'")
                   ndiss = arcpy.SelectLayerByAttribute_management(makldis, "NEW_SELECTION", "STRCONC ="  + "'" + elemt + "'")
                   for row in cursor:             
                        row[0] = b
                        if b > 0 :
                             row[1] = 1
                        else:
                             row[1] = 0
                        cursor.updateRow(row)
    Maintenant, ça tourne mais les sélections ne renvoient plus rien. ou en tout cas, arcpy.GetCount... renvois systématiquement 0.

    J'ai donc essayé de placer les sélections dans la deuxième boucle (
    Code:
    for rwo in elemt :
    ) puis dans le première (
    Code:
    for elmt in monsetcc:
    ) ainsi que différentes synthaxes.

    J'ai aussi essayé de faire une sélection dans Model builder et de l'exporter en python pour voir la syntaxe que renvoyait le script :


    Code:
    arcpy.SelectLayerByAttribute_management(buff_Layer, "NEW_SELECTION", "STRCONC = '141'")
    également testé une sélection directement dans arcmap avec like, = in() pour voir ce qui fonctionnait, mais rien à faire. J'ai un problème de syntaxe que je ne trouve pas.

  8. #8
    Quasi-modo Supporter(rice)

    Date d'inscription
    octobre 2008
    Messages
    998

    Par défaut Re : [PYTHON] Boucle sur les valeurs uniques d'un champ

    Je t'invites à consulter l'aide sur la création de requetes.
    Mais quelques tuyaux : "STRCONC = '141'" si STRCONC est un champ numérique, pas de ' autour de 141
    Attention au field delimiter qui change en fonction du workspace
    Pas besoin de like si tu as la valeur complete à chercher.
    Pas de = avant le in()

    Plus d'infos ici : http://desktop.arcgis.com/fr/arcmap/...expression.htm
    "Les sigé, c'est la balle !"
    Joey StarApic et Kool Shape du groupe MNT
    Album: Laisse pas trainer ton TIN

  9. #9

    Date d'inscription
    novembre 2013
    Localisation
    Genève
    Emploi
    Chargé de... travail...
    Messages
    53

    Par défaut Re : [PYTHON] Boucle sur les valeurs uniques d'un champ

    Salut Speed-Popeye,

    Ma sélection passe. Le problème n'est pas là.

    Mon script compare chaque valeur unique de ma couche 1 avec toutes celle de ma couche 2. J'ai donc créé 2 listes afin de poser comme condition "while élément_liste_1 == élément_liste_2 :" :


    Code:
     # Environnement de travail et variables représentant la gdb.
    wsp = arcpy.env.Workspace = arcpy.GetParameterAsText(0) #Dataset
    
    
    
    # Variables
        
    buff = arcpy.GetParameterAsText(1) #Fichier BUFFER brut
    dissbuff = arcpy.GetParameterAsText(2) #buffers < 50m fusionnés
    #prec = arcpy.GetParameterAsText(3) # Champ précision
    eli = "Elim" #Champ elimination des notes
    ctrl = "ctrl"
    conc = "conc"
    strconc ="STRCONC"
    sp = "NO_NOM_IF"
    pt = "PAS_TPS"
    #temp = "uptemp"
    maklay = arcpy.MakeFeatureLayer_management(buff, "maklay") #Passer buffer en layer
    makldis = arcpy.MakeFeatureLayer_management(dissbuff, "makldis")
    np = arcpy.SelectLayerByAttribute_management(maklay, "NEW_SELECTION", "XY_PRECISION_ORIGINAL > 50") #Selectionner les observations >50m de précision (elles seront découpées par les plus précises)
    
    #Boucle d'élimination des notes trop peu précises proches de notes plus précises par espèces et par pas de temps
    
         #Ajouter un champ 0/1 signalant les observations retenues ou non
    
    elim = arcpy.AddField_management(buff, eli, "SHORT")
    ctrl = arcpy.AddField_management(buff, ctrl, "TEXT")
    malistecc = []
    with arcpy.da.SearchCursor(np, "STRCONC") as scur:
         for r in scur:
              malistecc.append(r[0])
    monsetcc = set(malistecc)
    arcpy.AddMessage(monsetcc)
    
    malistedis = []
    with arcpy.da.SearchCursor(makldis, "STRCONC") as scur2:
         for r2 in scur2:
              malistedis.append(r[0])
    monsetdis = set(malistedis)
    arcpy.AddMessage(monsetcc)
    
    
    for elemt in monsetcc:
         for elediss in monsetdis:
              while elemt == elediss :
                   np2 = arcpy.SelectLayerByAttribute_management(np, "SUBSET_SELECTION",  "STRCONC ="  + "'" + elemt + "'")
                   ndiss = arcpy.SelectLayerByAttribute_management(makldis, "NEW_SELECTION", "STRCONC ="  + "'" + elemt + "'")
                   flds = ["ctrl", "Elim"]
                   with arcpy.da.UpdateCursor(buff, flds) as cursor:
                        for row in cursor:                        
                             a  = arcpy.SelectLayerByLocation_management (np2, "INTERSECT", ndiss)
                             b  = int(arcpy.GetCount_management(a).getOutput(0))
                             arcpy.AddMessage(b)
                             row[0] = b
                             if b > 0 :
                                  row[1] = 1
                             else:
                                  row[1] = 0
                             cursor.updateRow(row)
    
    del row, cursor, elemt, elediss
    Maintenant, b, me renvoi une seule valeur : 7 qui est aussi le nombre d'élément présent dans mes 2 listes et tourne pendant très longtemps.

    J'ai l'impression d'approcher du but parfois, mais plus souvent de me perdre...

  10. #10
    Quasi-modo Supporter(rice)

    Date d'inscription
    octobre 2008
    Messages
    998

    Par défaut Re : [PYTHON] Boucle sur les valeurs uniques d'un champ

    Sans les données c'est compliqué mais là rapidement, pourquoi le while ?
    un if suffit.
    Le plus efficace, souvent, c'est de coucher l'algo sur le papier et après de le coder quand on est un peu dans le flou.
    "Les sigé, c'est la balle !"
    Joey StarApic et Kool Shape du groupe MNT
    Album: Laisse pas trainer ton TIN

  11. #11

    Date d'inscription
    novembre 2013
    Localisation
    Genève
    Emploi
    Chargé de... travail...
    Messages
    53

    Par défaut Re : [PYTHON] Boucle sur les valeurs uniques d'un champ

    Je viens de réussir avec le model builder

    Un iterate feature selection pour prendre chaque valeur unique de mon champ STRCONC
    un select by attribute pour prendre les points ayant une valeur de précision =< 50m
    un select by attribute pour prendre ceux >50m
    select by location des >50m par ceux =< 50m
    et enfin calculate field pour leur attribuer un 1 dans un champ les signalant comme à écarter de mon jeu de données.
    Cliquez sur l'image pour la voir en taille réelle 

Nom : 		Export Graphic.jpg 
Affichages :	36 
Taille :		39,0 Ko 
ID : 			8649

    Simplissime sur le papier, mai je ne comprend pas où j'ai fauté dans mon script.

    Bref, au final, j'ai fait ce que je voulais.

    Merci beaucoup Speed-popeye pour les conseils et la réflection!

  12. #12
    Quasi-modo Supporter(rice)

    Date d'inscription
    octobre 2008
    Messages
    998

    Par défaut Re : [PYTHON] Boucle sur les valeurs uniques d'un champ

    Si tu veux tu peux exporter ton modèle en python pour enquêter !
    "Les sigé, c'est la balle !"
    Joey StarApic et Kool Shape du groupe MNT
    Album: Laisse pas trainer ton TIN

  13. #13

    Date d'inscription
    novembre 2013
    Localisation
    Genève
    Emploi
    Chargé de... travail...
    Messages
    53

    Par défaut Re : [PYTHON] Boucle sur les valeurs uniques d'un champ

    Yes, mais les iterateurs de ne sont pas faits pour Old Pyth...

    Mais c'est clair que je vais prendre le temps de trouver la solution!

 

 

Discussions similaires

  1. [QGIS 2.x] Nombre de valeurs uniques en fonction d'un champ par maille
    Par Mathias Pires dans le forum Assistance et Programmation
    Réponses: 4
    Dernier message: 19/01/2016, 10h59
  2. [QGIS 1.x] [QGIS 2.x] Nombre de valeurs uniques d'un champ d'une couche vecteur par maille
    Par Lolo Lepido dans le forum Assistance et Programmation
    Réponses: 6
    Dernier message: 18/11/2014, 17h16
  3. [ArcGIS 10.x] Mise en page _ légende _ valeurs uniques, plusieurs champs
    Par luluska dans le forum Assistance Technique
    Réponses: 3
    Dernier message: 11/04/2014, 20h56
  4. Réponses: 0
    Dernier message: 07/05/2008, 13h38
  5. [ArcGIS 9.x] Symbologie valeurs uniques
    Par natbo dans le forum Assistance Technique
    Réponses: 2
    Dernier message: 09/07/2007, 15h28

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •