Comment sélectionner des entités contenant une chaîne de texte spécifique à l'aide d'une expression dans QGIS

16

J'ai besoin de styliser un fichier de formes de polygone de parcelle d'arpentage, selon que le polygone est un claim minier ou non. Malheureusement, la seule information indiquant si un polygone est un claim minier ou non est contenue dans le champ "TITRE" de la table attributaire, qui donne le nom légal complet de la parcelle arpentée. Par exemple, «DISTRICT LOT 5639, BEING AWARD NO. 2 RÉCLAMATION MINÉRALE, KDYD '. J'ai besoin d'une expression qui sélectionne n'importe quelle entité contenant le texte "RÉCLAMATION MINÉRALE" dans le champ "TITRE".

Chris
la source

Réponses:

25

Tu dois juste utiliser l' LIKEopérateur.

Par exemple, "TITLE" LIKE '%MINERAL CLAIM%'

Le %symbole agit comme un caractère générique.

LIKEest sensible à la casse, alors qu'il ILIKEne l'est pas.

SaultDon
la source
Et sachez que c'est une opération lente, vous voudrez peut-être l'utiliser une fois pour générer une nouvelle colonne au lieu de l'avoir comme expression tout le temps.
bugmenot123
C'est lent pour une grande forme, donc j'ai simplement copié / collé la sélection comme un nouveau calque vectoriel.
Chris
@chris Vous pouvez utiliser cette même requête dans d'autres parties de QGIS comme une requête de définition ou stylisée à l'aide d'un rendu basé sur des règles - cela dépend vraiment de la raison pour laquelle vous devez appliquer la requête (c'est-à-dire, l'analyse, la visualisation, l'exportation, etc.). Les sélections sont un peu intensives mais si elles sont appliquées en tant que requête de définition, elles affichent uniquement ces fonctionnalités dans la requête sur le canevas ou les rendent disponibles pour le traitement. Essentiellement ce que vous avez fait lors du copier / coller de la sélection en tant que nouveau calque vectoriel.
SaultDon
Les index ne peuvent pas être utilisés avec LIKE, donc j'essaie toujours d'éviter de les refaire encore et encore. Mais oui, cela pourrait ne pas être pertinent, certainement avec de petits ensembles de données, il existe d'autres fruits à faible vitesse pour la vitesse.
bugmenot123
1
@ bugmenot123 Je viens d'apprendre que si vous avez un index lorsque vos données sont en postgresql, LIKE l'utilisera dans des conditions spécifiques (comme où le% est dans la requête) et ne fera pas de scan séquentiel! blog.cleverelephant.ca/2016/08/pgsql-text-pattern-ops.html
SaultDon
3

J'ai eu ce problème exact et l'ai résolu à partir de la console python avec regex. Bien que l'expression régulière puisse être délicate, elle est très puissante. Et vous vous retrouverez avec un outil que vous pouvez utiliser avec des cas de match plus difficiles. Voici les documents . et voici une belle machine en ligne pour tester vos chaînes d'expression régulière.

Tout d'abord, voici le script rapide que j'exécute pour vérifier mes chaînes d'expression régulière dans qgis

import re
RES_STRING='MINERAL CLAIM'
REGEX_HAYSTACK='DISTRICT LOT 5639, BEING AWARD NO. 2 MINERAL CLAIM, KDYD'

REGEX_STRING=re.compile(RES_STRING)
print "searching for "+RES_STRING+" in "+REGEX_HAYSTACK
REGEX_MATCH = REGEX_STRING.search(REGEX_HAYSTACK)
if REGEX_MATCH:
    print "found '"+REGEX_MATCH.group()+"'"
else:
    print "No match found"

Une fois que vous êtes satisfait de votre correspondance regex, vous pouvez l'intégrer dans une fonction pour fournir une sélection de toutes les fonctionnalités qui correspondent. Voici une fonction pour faire exactement cela.

def select_by_regex(input_layer,attribute_name,regex_string):
    import re
    RES_STRING=regex_string
    attribute_name_idx = input_layer.fieldNameIndex(attribute_name)
    if attribute_name_idx<0:
        raise valueError("cannot find attribute"+attribute_name)
    else:
        fids=[]
        for feature in input_layer.getFeatures():
            REGEX_HAYSTACK=feature[attribute_name_idx]
            REGEX_STRING=re.compile(RES_STRING)
            REGEX_MATCH = REGEX_STRING.search(REGEX_HAYSTACK)
            if REGEX_MATCH:
                fids.append(feature.id())
            else:
                pass
        input_layer.setSelectedFeatures(fids)


#USAGE BIT
input_layer = QgsVectorLayer('path/to/shape/file.shp','layer name', 'ogr')
QgsMapLayerRegistry.instance().addMapLayer(input_layer)   
regex_string='MINERAL CLAIM'
attribute_name='TITLE'
select_by_regex(input_layer,attribute_name,regex_string)

Vous devrez l'enregistrer dans un fichier et l'exécuter à partir de l'ide python qgis.

(non testé mais assez confiant)

Mr Purple
la source
1
Excellent conseil pour apprendre l'expression régulière, mais exagéré pour le problème actuel.
alphabetasoup
@ alpha-beta-soup true. Dans ce cas. Cependant, des problèmes TRÈS similaires le trouveraient certainement indispensable. numéros de lot <6000? ou les 2 premiers claims miniers? C'est juste une autre réponse (bien que beaucoup plus complexe / puissante). Peut-être que cela aidera quelqu'un d'autre.
Mr Purple
3
Notez également que QGIS a une fonction de correspondance d'expression régulière intégrée - regexp_match.
ndawson
Certainement la réponse la plus "approfondie". Un peu exagéré pour ce dont j'ai besoin, mais appréciez quand même. Cela aidera à coup sûr les autres à l'avenir.
Chris