Cari jika bidang ada di kelas fitur

9

Saya memiliki beberapa lusin kelas fitur, salah satunya berisi bidang yang saya cari. Mereka disimpan dalam beberapa file geodatabases yang berbeda.

Apakah ada cara cepat mencari setiap kelas fitur untuk menemukan yang memiliki bidang saya? Atau apakah saya harus memeriksa tabel atribut masing-masing dalam Katalog? Beberapa file memiliki nama yang sama tetapi disimpan di lokasi yang berbeda.

Saya ingin dapat melakukan ini di dalam Calculate Valuealat di ModelBuilder, sehingga setiap kali saya perlu, saya bisa menjalankan model pada satu file gdb dan akan mencari melalui semua kelas fitur dalam gdb itu dan mencari bidang .

Sejauh ini, saya memiliki iterator kelas fitur yang beralih ke semua kelas fitur dalam file gdb secara rekursif. Di dalam Calculate Valuesaya memiliki kode berikut:

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"

Nilai yang dikembalikan dikumpulkan Output Valuessebagai string. Output untuk semua kelas fitur telah "tidak ditemukan", meskipun bidang ada di setidaknya 4 dari mereka. masukkan deskripsi gambar di sini

Cindy Jayakumar
sumber
Apa yang Anda coba hitung nilainya? Apakah Anda mencoba memasukkan catatan ke dalam tabel? Tidak masuk akal apa yang Anda coba gunakan alat Hitung Nilai untuk ...
RyanKDalton
Saya telah meletakkan kode Python di dalam Calculate Valueuntuk mencari bidang, dan mengembalikan jalur kelas fitur sebagai string jika menemukan bidang - lihat jawaban saya di bawah ini.
Cindy Jayakumar

Jawaban:

5

Saya lebih suka pemahaman daftar daripada operasi string (seperti jawaban yang diterima). Menurut pendapat saya, ini lebih mudah dibaca dan pythonic. Lebih jauh, pendekatan pemahaman daftar dapat diperluas dengan menambahkan fungsionalitas lebih lanjut ( str.lower(), seperti yang dilakukan @RyanDalton) dengan sangat mudah.

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

Jika Anda lebih suka satu kalimat jika-pernyataan lain:

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

Atau bahkan lebih pendek, tetapi kurang mudah dibaca:

    def findField(fc, fi):
      return "found in " + fc if fi in [field.name for field in arcpy.ListFields(fc)] else "not found in " + fc
Saleika
sumber
Ya ini akan menjadi jawaban yang lebih disukai sekarang. Saya menanyakan pertanyaan ini sejak lama, sangat menyakitkan saya untuk mengingat 9 bulan yang saya buang di ModelBuilder sebelum beralih ke Python sepenuhnya alih-alih meretas bersama potongan-potongan.
Cindy Jayakumar
20

Periksa fungsi ini dari oleh Bjorn Kuiper untuk menguji apakah ada bidang :

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

    fieldCount = len(fieldList)

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

dengan contoh penggunaan berikut:

    if (not FieldExist(myFeatureClass, "myField")):
      arcpy.AddError("Field 'myField' does not exist in " + myFeatureClass)
      sys.exit()
Dana
sumber
Saya akhirnya menggunakan sesuatu yang serupa beberapa waktu lalu, tapi itu tidak cukup memberikan hasil yang saya cari.
Cindy Jayakumar
12

Anda bisa menggunakan arcpy:

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

Selain itu, Anda dapat menggunakan os.walk untuk file di drive Anda sebagai:

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

semoga membantu ....

Aragon
sumber
Saya mencobanya, dan sementara kodenya masuk akal, tidak melakukan apa-apa. Saya mengujinya dengan menggunakan bidang yang ada di empat kelas fitur saya - skrip berlari tetapi tidak menghasilkan apa-apa.
Cindy Jayakumar
oh maaf, saya lupa untuk loop bidang di bidang, sekarang saya memperbarui jawaban saya dan saya telah mengujinya.
Aragon
Saya telah mencoba dengan kode yang diperbarui, ini berjalan tetapi tidak ada output meskipun bidangnya ada dalam beberapa kelas fitur dalam geodatabase.
Cindy Jayakumar
3

Arabella, apakah kacamata feature Anda di Feature Datasets? Jika demikian, solusi @ Aragon tidak akan berfungsi karena Anda perlu menelusuri kumpulan data fitur dan kemudian memeriksa kacamata feature.

Menggunakan kode @ Aragon serta kode @ gotchula dari Daftar semua kelas fitur di GDB, termasuk dalam dataset fitur , saya menghasilkan kode berikut yang akan membaca semua dataset fitur dan kacamata fitur dalam geodatabase.

CATATAN : Secara default, ListFields tampaknya peka terhadap huruf besar-kecil. Saya telah menambahkan kode untuk mengonversi fieldname yang ditentukan pengguna dan nama ListField ke huruf kecil untuk pencarian case-insensitive. Anda mungkin juga ingin menonaktifkan sebagian besar pernyataan cetak, tetapi saya membiarkannya di sana sehingga Anda dapat mengikuti kode ketika sedang berjalan. Saya juga membuat subfungsi FindField di dalam sehingga saya bisa menyebutnya beberapa kali dalam skrip tanpa harus kode ulang.

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)
RyanKDalton
sumber
Saya akan menjalankan ini dalam model, jadi saya mengadaptasinya sedikit dan mengujinya. Saya tidak yakin apa yang ingin saya Calculate Valuekembalikan - bisakah saya return "true" if FindField(fc,myField) =="true" else "false"?
Cindy Jayakumar
Ah, baru sadar bahwa komentar saya sebelumnya tidak akan memberi tahu saya apa-apa. Juga menjalankan tes boolean di dalam model tidak mengembalikan apa pun.
Cindy Jayakumar
Nilai Kalibrasi? Tes Boolean? Saya pikir Anda harus mengklarifikasi pertanyaan Anda tentang apa sebenarnya yang Anda cari.
RyanKDalton
Saya telah mengedit pertanyaan.
Cindy Jayakumar
2

Beberapa telah menari di sekitar cara saya akan melakukan ini, tetapi saya hanya ingin menambahkan cara satu-line yang mudah untuk melakukan ini:

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

Apa yang mungkin lebih berguna (jika Anda mengulangi banyak fitur kelas) Saya akan menggunakan kebalikan dari yang di atas sebagai filter:

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.
mr.adam
sumber
1

Temukan jawabannya dengan bantuan kode dalam menjawab pertanyaan ini . Saya mengambil semua nama bidang, mengubahnya menjadi string dan kemudian mencari string untuk bidang saya. Kode di Calculate Valuesekarang terlihat sebagai berikut:

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

The Output Valuessekarang berisi daftar lengkap kelas fitur yang memiliki bidang saya mencari, dan not founduntuk sisanya.

Kumpulkan output Nilai

Cindy Jayakumar
sumber