Suchen Sie, ob ein Feld in der Feature-Class vorhanden ist


8

Ich habe ein paar Dutzend Feature-Classes, von denen eine das gesuchte Feld enthält. Sie werden in verschiedenen Geodatabases gespeichert.

Gibt es eine schnelle Möglichkeit, jede Feature-Class zu durchsuchen, um die mit meinem Feld zu finden? Oder muss ich die Attributtabelle jedes einzelnen im Katalog überprüfen? Einige der Dateien haben denselben Namen, werden jedoch an verschiedenen Orten gespeichert.

Ich möchte dies in einem Calculate ValueTool in ModelBuilder tun können, damit ich das Modell jedes Mal auf einer einzelnen Datei-GDB ausführen und alle Feature-Classes in dieser GDB durchsuchen und nach dem Feld suchen kann .

Bisher habe ich einen Feature-Class-Iterator, der alle Feature-Classes in der Datei gdb rekursiv durchläuft. Im Inneren habe Calculate Valueich folgenden Code:

findField(r"%Feature%", "%Search Field%")

def findField(fc, fi):
  lst = arcpy.ListFields(fc)
  for f in lst:
    if f.name == fi:
      return fc
    else:
      return "not found"

Die zurückgegebenen Werte werden Output Valuesals Zeichenfolgen gesammelt . Die Ausgabe für alle Feature-Classes wurde "nicht gefunden", obwohl das Feld in mindestens 4 von ihnen vorhanden ist. Geben Sie hier die Bildbeschreibung ein


Wovon versuchen Sie den Wert zu berechnen? Versuchen Sie, Datensätze in eine Tabelle einzufügen? Es macht nicht viel Sinn, wofür Sie das Tool "Wert berechnen" verwenden
möchten

Ich habe den Python-Code in das Calculate ValueFeld eingefügt , um nach dem Feld zu suchen und den Pfad der Feature-Class als Zeichenfolge zurückzugeben, wenn sie das Feld findet - siehe meine Antwort unten.
Cindy Jayakumar

Antworten:


4

Ich würde ein Listenverständnis anstelle von Zeichenfolgenoperationen bevorzugen (wie akzeptierte Antwort). Meiner Meinung nach ist dies lesbarer und pythonischer. Darüber hinaus könnte der Ansatz des Listenverständnisses erweitert werden, indem str.lower()sehr einfach weitere Funktionen hinzugefügt werden ( wie dies bei @RyanDalton der Fall war).

def findField(fc, fi):
  fieldnames = [field.name for field in arcpy.ListFields(fc)]
  if fi in fieldnames:
    return "found in " +fc
  else:
    return "not found in " +fc

Wenn Sie den Einzeiler bevorzugen if-else Statement:

def findField(fc, fi):
  fieldnames = [field.name for field in arcpy.ListFields(fc)]
  return "found in " + fc if fi in fieldnames else "not found in " + fc

Oder noch kürzer, aber weniger lesbar:

    def findField(fc, fi):
      return "found in " + fc if fi in [field.name for field in arcpy.ListFields(fc)] else "not found in " + fc

Ja, das wäre jetzt die bevorzugte Antwort. Ich habe diese Frage vor so langer Zeit gestellt, dass es mir weh tut, mich an die 9 Monate zu erinnern, die ich mit ModelBuilder verschwendet habe, bevor ich vollständig zu Python gewechselt bin, anstatt Teile zusammen zu hacken.
Cindy Jayakumar

19

Schauen Sie sich diese Funktion von Björn Kuiper an, um zu testen, ob ein Feld vorhanden ist :

def FieldExist(featureclass, fieldname):
    fieldList = arcpy.ListFields(featureclass, fieldname)

    fieldCount = len(fieldList)

    if (fieldCount == 1):
        return True
    else:
        return False

mit folgendem Anwendungsbeispiel:

    if (not FieldExist(myFeatureClass, "myField")):
      arcpy.AddError("Field 'myField' does not exist in " + myFeatureClass)
      sys.exit()

Ich habe vor einiger Zeit etwas Ähnliches verwendet, aber es gab nicht ganz die Ausgabe, die ich suchte.
Cindy Jayakumar

12

Sie können arcpy verwenden:

import arcpy

myField = "test"

env.workspace = "D:/test/data.gdb"
fcs = arcpy.ListFeatureClasses()

for f in fcs:
    fieldList = arcpy.ListFields(f)
    for field in fieldList:   
         if field.name == myField:
             print f

Außerdem können Sie os.walk für Dateien in Ihrem Laufwerk verwenden als:

path = r"C:"
for root, dirs, files in os.walk(path):
    for fileName in files:
            .........

ich hoffe es hilft dir ....


Ich habe es versucht, und obwohl der Code Sinn macht, macht er nichts. Ich habe es mit einem Feld getestet, das sich in vier meiner Feature-Classes befindet. Das Skript wurde ausgeführt, hat jedoch nichts ausgegeben.
Cindy Jayakumar

Oh, Entschuldigung, ich habe vergessen, Felder im Feldsatz zu schleifen. Jetzt aktualisiere ich meine Antwort und habe sie getestet.
Aragon

Ich habe versucht, mit dem aktualisierten Code, es läuft, aber keine Ausgabe, obwohl das Feld in mehreren Feature-Classes innerhalb der Geodatabase ist.
Cindy Jayakumar

3

Arabella, befinden sich Ihre Feature-Classes in Feature-Datasets? In diesem Fall funktioniert die Lösung von @ Aragon nicht, da Sie die Feature-Datasets durchgehen und dann die Feature-Classes überprüfen müssen.

Unter Verwendung des Codes von @ Aragon sowie des Codes von @ gotchula aus Alle Feature-Classes in GDB auflisten , einschließlich innerhalb von Feature-Datasets , habe ich den folgenden Code erstellt, der alle Feature-Datasets und Feature-Klassen in einer Geodatabase durchliest.

HINWEIS : Standardmäßig wird bei ListFields zwischen Groß- und Kleinschreibung unterschieden. Ich habe Code hinzugefügt, um sowohl den benutzerdefinierten Feldnamen als auch den ListField-Namen für Suchvorgänge ohne Berücksichtigung der Groß- und Kleinschreibung in Kleinbuchstaben umzuwandeln. Sie möchten wahrscheinlich auch die meisten Druckanweisungen deaktivieren, aber ich habe sie dort belassen, damit Sie dem Code folgen können, während er ausgeführt wird. Ich habe auch die Unterfunktion FindField innerhalb von erstellt, damit ich sie im Skript mehrmals aufrufen kann, ohne sie neu codieren zu müssen.

import arcpy

def FindField(fc,myField):
    fieldList = arcpy.ListFields(fc)
    for field in fieldList:
        if str.lower(str(field.name)) == str.lower(myField):
            print "    " + fc + " contains fieldname: " + myField

myField = "test"
arcpy.env.workspace = "D:/test/data.gdb"

#Search root level featureclasses
for fc in arcpy.ListFeatureClasses():
    print "Searching root level Featureclasses..."
    print "  Searching " + fc
    FindField(fc,myField)

#Search Feature Datasets
for fds in arcpy.ListDatasets('','feature'):
    print "Searching FeatureDataset: " + fds

    for fc in arcpy.ListFeatureClasses('','',fds):
        print "  Searching Featureclass... " + fc
        FindField(fc,myField)

Ich würde dies in einem Modell ausführen, also habe ich es leicht angepasst und getestet. Ich bin mir nicht sicher, was ich möchte, dass das Calculate Valuezurückkommt - könnte ich return "true" if FindField(fc,myField) =="true" else "false"?
Cindy Jayakumar

Ah, ich habe gerade festgestellt, dass mein vorheriger Kommentar mir nichts sagen würde. Auch das Ausführen dieses booleschen Tests im Modell gibt nichts zurück.
Cindy Jayakumar

Wert berechnen? Boolescher Test? Ich denke, Sie sollten Ihre Frage klären, wonach Sie genau suchen.
RyanKDalton

Ich habe die Frage bearbeitet.
Cindy Jayakumar

2

Einige haben so getanzt, wie ich das machen würde, aber ich möchte nur einen einfachen einzeiligen Weg hinzufügen, um dies zu tun:

if 'fieldname' in [f.name for f in arcpy.ListFields(fc)]:
    ## do something.

Was ist vielleicht nützlicher (wenn Sie viele Feature-Classes durchlaufen)? Ich würde das Gegenteil von oben als Filter verwenden:

for fc in arcpy.ListFeatureClasses():
    if not 'fieldname' in [f.name for f in arcpy.ListFields(fc)]:
        continue
    ## now do something with the feature class.

1

Ich habe die Antwort mit Hilfe des Codes in der Antwort auf diese Frage gefunden . Ich nahm alle Feldnamen, konvertierte sie in eine Zeichenfolge und suchte dann in der Zeichenfolge nach meinem Feld. Der Code im Calculate Valuejetzt sieht wie folgt aus:

def findField(fc, fi):
  fieldList = arcpy.ListFields(fc)
  nameList = []
  for f in fieldList:
    nameList.append(f.name)
  str_lst = "!" + "!, !".join(nameList) + "!"
  return "found in" +fc if str_lst.find(fi) > 0 else "not found in " +fc

Das Output Valuesenthält jetzt die vollständige Liste der Feature-Classes mit dem Feld, nach dem ich gesucht habe, und not foundfür den Rest.

Ausgabe der gesammelten Werte

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.