Filtrować funkcje na podstawie ich atrybutów za pomocą Pythona?

16

Jak uzyskać funkcje według ich atrybutów (podobnych do Iqueryfilter w arcobjects) w Qgis przy użyciu Pythona? Czy zamiast pobierać wszystkie funkcje i filtrować je ręcznie, istnieje jakaś opcja użycia klauzuli where, aby ją odfiltrować?

Przykład: Mam nazwę pola o nazwie „Hrabstwa”. Ma ponad pięćdziesiąt tysięcy funkcji. Nie można pobrać wszystkich funkcji i przefiltrować ze względu na czasochłonność. Mogę więc wykonać zapytanie za pomocą iqueryfilter.whereclause = 'Counties = Norwich' w arcobjects. Podobne rzeczy potrzebuję w PyQgis.

venkat
źródło
1
@NathanW tak masz rację. Potrzebuję tylko zwrócić dane przy użyciu zapytania z warstwy. czy mógłbyś podać mi jakiś przykład w pyqgis?
venkat
@NathanW Cześć, mam to. działa jak zapytanie definicji w arcgis. zobacz ten przykład. t = outputLayer.setSubsetString ('UniqID =' + inputFeat.attribute ("UniqID"). toPyObject ()) jeśli t == True: outputProvider = outputLayer.dataProvider () print outputProvider.featureCount () tzn. zwróci tylko zapytanie zadowolone dane
venkat,
@venkat gdzie w QGIS umieszczasz zapytanie? Dzięki.
ianbroad

Odpowiedzi:

12

Silnik wyrażeń QGIS jest w stanie to zrobić przy użyciu QgsFeatureRequest.setFilterExpression( unicode )metody (od QGIS 2.2)

request = QgsFeatureRequest().setFilterExpression( u'"Counties" = \'Norwich\'' )
it = l.getFeatures( request )

Począwszy od QGIS 2.10 jest nawet możliwe, że takie filtrowanie zapewni dodatkową wydajność w porównaniu z innymi typami filtrowania (takimi jak implementacje Pythona).

Zasadniczo ma to zastosowanie, jeśli spełnione są następujące trzy warunki:

  • Używasz warstwy z dostawcą Postgis W tej chwili (2.16) implementuje to znacznie więcej niż tylko dostawca Postgis (spatialite, ogr, oracle ...).
  • Twoja ekspresja nie jest zbyt skomplikowane (rzeczy podoba >, =, IN, NOT NULL... są obsługiwane)
  • Włączyłeś tę funkcję w Ustawienia> Opcje> Źródła danych> Obsługa źródła danych> Wykonaj wyrażenie po stronie serwera Postgres
  • Korzyść z wydajności jest optymalna dzięki odpowiednim indeksom w tabelach bazy danych

Z QGIS 3.0 jest to nawet możliwe

features = l.getFeatures('"Counties" = \'Norwicth\'')
Matthias Kuhn
źródło
1

W tym poście - który można uznać za odpowiedź na zduplikowane pytanie - szczegółowo opisano, jak pobrać wszystkie atrybuty z warstwy. Autor opisuje proces, którego szukasz, ręcznie filtrując dane po ich zwróceniu. Jest to całkiem kompletne odniesienie, a ich link naprawdę powinien ci pomóc.

Tomek
źródło
2
To nie jest duplikat pytania. nie chcę pobierać wszystkich atrybutów z warstwy. Najpierw przefiltruj, a następnie chcę pobrać funkcje spełniające kryteria filtru. tzn. wydajność jest znacznie lepsza.
venkat
1

Za pomocą zapytania SQL można to również łatwo zrobić za pomocą ogr. Możesz wykonać ten kod na przykład w konsoli python QGIS lub w samodzielnym skrypcie.
Przykład :

from osgeo import ogr

path = "path to your shapefile.shp"
ID = "FieldID" # For instance 'Countries' 
datasource = ogr.Open(str(path)) # your datasource

layer = datasource.GetLayer(0) # Import layer 0 --> only works with shapefiles
layerName = str( layer.GetName() )# Save the Layersname first

# Do the sql query
# Selects all features from a layer datasource where Field Countries is equal to 'Germany'
layers = datasource.ExecuteSQL("SELECT * FROM %s WHERE %s = '%s'" % (layerName, ID, 'Germany') )
res = []
for i in range(0,layers.GetFeatureCount()):
   f = layers.GetFeature(i)
   g = f.GetGeometryRef()
   res.append(g.Area()) 

# res now contains the measured area of each feature where the attribute ID has the value 'Germany'
Kulik
źródło
0

Określanie filtrów SQL nie jest jeszcze obsługiwane przy użyciu interfejsu API QGIS od wersji 1.9.

Jak rozumiem z tego artykułu z listy mailingowej , obsługa „SQL dostawcy natywnego” będzie dostępna tylko w przyszłej wersji.

vinayan
źródło