In the previous section, we viewed vector layer fields and attributes. Now let’s use these attributes to put a filter on our layer so that it only contains certain features.
For example, this is how we can filter our countries vector layer to only features where the ADMIN value starts with an A:
vlayer.setSubsetString("ADMIN LIKE 'A%'") for feature in vlayer.getFeatures(): print(feature["ADMIN"])
This code is the equivalent of going to the layer properties and entering ADMIN LIKE ‘A%’ in the provider feature filter.
To remove the filter, we set an empty subset string:
vlayer.setSubsetString("") for feature in vlayer.getFeatures(): print(feature["ADMIN"])
To make our code more flexible, we can use a variable to define the character we want to filter for. The advantage of using a variable is that we only need to define it once and then we can use it in multiple places within our code. And if we eventually want to change it to a different character, we only have to change it in one place. The following code shows two different approaches for inserting a variable into a string:
my_char = "C" vlayer.setSubsetString("ADMIN LIKE '"+my_char+"%'") print("The following country names start with {}:".format(my_char)) for feature in vlayer.getFeatures(): print(feature['ADMIN'])
The first approach is to concatenate strings using + operators. The second approach is called string formatting and the above syntax (with curly brackets) is specific to Python 3 (and thus requires QGIS 3).
String formatting looks complicated at first sight but it is also really powerful. For example, we can output the number of people living in each country using:
for feature in vlayer.getFeatures(): print("{pop:.2f} mio people live in {name}".format(name=feature['ADMIN'],pop=feature['POP_EST']/1000000))
4.51 mio people live in Central African Republic
33.49 mio people live in Canada
16.60 mio people live in Chile
...
This is interesting for multiple reasons: first, the parameters in the format function can be provided in any order because we assigned them names (pop and name in this example). Second, we formatted the population value to display two digits after the decimal separator. For more string formatting examples see the official Python documentation.
This is one way to filter the features in a vector layer. You also saw some different methods for integrating variables into strings using either the + operator or string formatting.
PyQGIS 101 is a work in progress. I’d appreciate any feedback, particularly from beginners!
my_char = “C”
vlayer.setSubsetString(“ADMIN LIKE ‘”+my_char+”%'”)
print(“The following country names start with {}:”.format(my_char))
for feature in vlayer.getFeatures():
print(feature[‘ADMIN’])
why does replacing the first line of code from above with
my_char = input(“Enter Char”)
not work?
I assume input(“Enter Char”) is an attempt to make the script interactive but this is not the way to achieve interactivity in PyQGIS. I’ll definitely get into this topic later.
Hi, I can’t differentiate the “two approaches” that you mention above. Can you please be more specific?
Thanks, I’m learning a lot!
Approach #1 is string concatenation using + operators:
"ADMIN LIKE '"+my_char+"%'"
Approach #2 is string formatting:
"ADMIN LIKE '{}%'".format(my_char)
I hit my first major challenge here. I’ve never thought of using LIKE in the query builder. I don’t think I ever noticed its existence until this tutorial.
So, I had to google it, the search led me to learning about wildcards.
Also, the formatting was challenging but now I love it.
Lastly, and this is a question, how do I tell qgis to perform a function on an already added layer instead of creating a new layer every time I update my code?
Thanks ma’am for the benefits.
You can use
vlayer=iface.activeLayer()
to the currently active loaded layer.Works! Thanks ma.
Hello,
According to the previous part of the tutorial and from what I’ve understood, I suggest to replace (in the project already containing ne_10m_admin_0_countrie
the “vlayer = iface.addVectorLayer(path, “countries”, “ogr”)”
by “vlayer=iface.activeLayer()”
Good point, Luc!
Hello, Thanks for the tutorial I am a beginner,
I try string formatting, but I have this error
UnicodeEncodeError: ‘ascii’ codec can’t encode character u’\xe9′ in position 10: ordinal not in range(128).
Please help me. Thanks
I try to put # -*- coding: utf-8 -*- as first line of the script but its does’nt work.
Hi, I could not find ‘SetSubsetString’ option through the list. I am working with QGIS 2.18, How can I solve this problem?
These tutorials require QGIS3. The PyQGIS API has changed.
Hi thank you for your blog, it’s very helpful. Unfortunately QGIS Filter still has an unsolved bug – LIKE operator is not case-sensitive.
For example:
vlayer.setSubsetString(“FIELD_NAME LIKE ‘%Wola'”)
returns features where the FIELD_NAME values ends with ‘wola’, e.g. Tywola, Suchowola etc.
Is it possible to run setSubsetString function using re.match or regexp_match or anything similar?
As far as I know, the subset string / filter specified for a layer is passed directly to the underlying OGR provider. Therefore only syntax supported by OGR https://gdal.org/user/sql_sqlite_dialect.html can be used.
Hi,
Thank you very much for this tutorial!
I have a question about the print function. Why do you use 2 quotes at one time and 1 at other times:
Hi Laura. In Python, single and double quotes can be used interchangeably. There is no difference between
print(feature["ADMIN"])
andprint(feature['ADMIN'])
.And another question;
I want to use as much variabele as posible(sorry its Dutch):
Last line, rename the variable: veld_gebrdoel into the fieldname “gebruiksdo” goes well, but it isn’t a variabele anymore. and I have to edit this line everytime:
How can I use a variabele in the printfeature line?
Use
print(feature[veld_gebrdoel])
That make sense. Thank you!
how much of an expression can this method handle? Any other suggestions to accomplish the same task with a different route? The length of the expression was around 47,000 characters.
2020-06-12T10:57:22 CRITICAL Layer MUPOLYGON : OGR[3] error 1: SQL Expression Parsing Error: memory exhausted. Occurred around :
‘77231’,’77242′,’77245′,’77249′,’77251′,’77253′,’77282′,’76207′,’76221′,’76229′,
I’m not aware of the exact limits but there seem to be workarounds http://www.samuelbosch.com/2016/08/workaround-for-sql-expression-parsing.html
I can’t get the code to work with field names with spacing in for example ‘field_name’ works but “field name” doesn’t.
Hello !
I discovered that : vlayer.setSubsetString(“ADMIN” LIKE ‘A%’) doesn’t work for me,
but vlayer.setSubsetString(‘ADMIN LIKE \’A%\’ ‘) does.
Also vlayer.setSubsetString(‘ “ADMIN” LIKE \’A%\’ ‘) does work too.
Can you explain why there is this different behaviour between your qgis and mine please ?