Filtrer les fonctionnalités en fonction de leurs attributs à l'aide de Python?

16

Comment obtenir des fonctionnalités par leurs attributs (similaires à Iqueryfilter dans les arcobjects) dans Qgis en utilisant python? Au lieu d'obtenir toutes les fonctionnalités et de les filtrer manuellement, existe-t-il une option pour utiliser la clause where pour les filtrer?

Exemple: J'ai un nom de champ appelé «Comtés». Il a plus de cinquante mille fonctionnalités. Il n'est pas possible de récupérer toutes les fonctionnalités et de les filtrer en raison du temps. Je peux donc l'interroger en utilisant iqueryfilter.whereclause = 'Counties = Norwich' dans les arcobjects. La même chose dont j'ai besoin dans PyQgis.

venkat
la source
1
@NathanW oui vous avez raison. j'ai seulement besoin de renvoyer les données en utilisant une requête de la couche. pourriez-vous s'il vous plaît me donner un exemple en pyqgis?
venkat
@NathanW Salut, j'ai compris. son fonctionnement comme requête de définition dans arcgis. voir cet exemple. t = outputLayer.setSubsetString ('UniqID =' + inputFeat.attribute ("UniqID"). toPyObject ()) if t == True: outputProvider = outputLayer.dataProvider () print outputProvider.featureCount () ie il ne renverra que la requête données satisfaites
venkat
@venkat où dans QGIS mettez-vous la requête? Merci.
ianbroad

Réponses:

12

Le moteur d'expression QGIS est capable de le faire en utilisant la QgsFeatureRequest.setFilterExpression( unicode )méthode (depuis QGIS 2.2)

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

À partir de QGIS 2.10, il est même possible que le filtrage de cette manière vous donne des performances supplémentaires par rapport à d'autres types de filtrage (comme les implémentations python).

Fondamentalement, cela s'applique si les trois conditions suivantes sont remplies:

  • Vous utilisez une couche avec le fournisseur de postgis À l'heure actuelle (2.16), bien plus qu'un simple fournisseur de postgis l'implémente (spatialite, ogr, oracle ...).
  • Votre expression est pas trop compliqué ( des choses comme >, =, IN, NOT NULL... sont pris en charge)
  • Vous avez activé cette fonctionnalité dans Paramètres> Options> Sources de données> Gestion des sources de données> Exécuter l'expression côté serveur postgres
  • L'avantage de performance est optimal avec des index appropriés sur les tables de base de données

Avec QGIS 3.0, il est même possible de faire simplement

features = l.getFeatures('"Counties" = \'Norwicth\'')
Matthias Kuhn
la source
1

Ce message - qui pourrait être considéré comme une réponse à une question en double - détaille comment récupérer tous les attributs d'une couche. L'auteur décrit le processus que vous recherchez comme un filtrage manuel des données une fois qu'elles sont retournées. C'est une référence assez complète et leur lien devrait vraiment vous aider.

À M
la source
2
Ce n'est pas une question en double. je ne veux pas récupérer tous les attributs d'une couche. Filtrez-le d'abord, puis je veux récupérer les fonctionnalités qui relèvent des critères de filtre. c'est-à-dire que les performances sont bien meilleures.
venkat
1

En utilisant une requête SQL, il est également facilement possible avec ogr. Vous pouvez exécuter ce code par exemple dans la console python QGIS ou un script autonome.
Exemple :

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'
Courlis
la source
0

La spécification des filtres SQL n'est pas encore prise en charge à l'aide de l'API QGIS à partir de la version 1.9.

Si je comprends bien cet article de la liste de diffusion , la prise en charge de "SQL du fournisseur natif" ne sera disponible que dans une future version.

vinayan
la source