You can use the script below in QGIS Python Editor. It takes about 45 seconds (including saving to source file) for 1.5 million features in SSD or HDD. Select the layer first.
start_time = time.time()
layer = iface.activeLayer()
# Add CUM_SUM field if not exist
field_index = layer.fields().indexFromName("CUM_SUM")
if field_index == -1:...
Create a new function using Function Editor.
Copy/paste the following script:
from qgis.core import *
from qgis.gui import *
ns = re.compile('([0-9]+)')
return [int(t) if t.isdigit() else t.lower() for t in re.split(ns, s)]
@qgsfunction(args='auto', group='Custom', usesgeometry=False)
If you're calculating into the same column that you're getting values from, you always run the risk of losing/messing up the values in that column.
In your case, you'd already calculated the column, so hab values that had already been changed did not match anything in your if: elif: statement and because you didn't explicitly return anything your function ...
You can use Field calculator to create a new field with the following expression, using a case statement. You can add as many when conditions as you like:
when "areacode" = 1 then 'one'
when "areacode" = 2 then 'two'
For all other cases (e.g. you defined areacodes 0 to 12, and now want to define a result for values ...
You probably use shapefiles to store your layer. To solve your issue, save the layer to a Geopackage.
Shapefiles do not support Datetime field types. See the QGIS documentation about Shapefiles:
Only Decimal number, Whole number, Text data and Date attributes are
See also this explanation.
Two approaches that resolve different parts of the problem and could maybe help finding an easier solution. Approach 3 solves the problem, based on approach 2, but is similarily complex as your initial expression.
Approach 1: array_prioritize
Integer-only elements will be sorted correctly, combined alpha-numerical strings will be put at the end:
Use the Field calculator with a CASE-statement. The expression looks like this, where "vegetation_type" is the name of the field containing the WC1, WC2 values:
when "vegetation_type" in ('WC1', 'WC2') then 'Wet Coniferous Forest Group'
Before the end statement, you can add as many similar when ... then statements as you ...
Your expression is not efficient because it calculates the same sum over and over again: for feature no. 100, it is adding 100 numbers (feature1, feature2, ... feature100), even though adding 99% of these values (from feature1 to feature99) was done before.
Better rely on the already calculated sum of the last feature: for feature 100, something like (...
A slightly different approach to solving the problem from the solutions till now proposed is the following expression:
Building on this answer, you can first find the relative angle between the current point and the previous point then use that angle as a condition for your speed in the distance/speed calculation for your Date & Time type field.
I used 50 m distance between points and a 30 degree threshold just to demonstrate.
I set the fast and slow speeds to 14 m/s and ...
Another way of doing it would be to define a lookup table - a table with two columns areacode (int) and label (varchar). Then you fill in the table:
areacode | label
1 | One areacode
2 | Another areacode
and so on. When the table is complete, you can join it with your initial coverage.
if name.count('City of')>1:
newname =  #Create a list
[newname.append(word) for word in name.split(' ') if word not in newname] #Split the string at each space, append word to list if it isnt already in it
newname = ' '.join(newname) #Join back to a string
Another way of doing this which may work better if you have a dynamic data set, would be to make a look-up table. i.e. a table with two fields type and group and then fill in the table with the actual groups,
type | group
WC1 | Wet Coniferous
WC2 | Wet Coniferous
WC3 | Another group
WC4 | Something else
Then you join this ...
You need to switch the order of your two arrays within array_all(), like this:
WHEN array_all(array('A','A'),array_distinct(string_to_array(@myarray))) THEN 'A'
WHEN array_all(array('A','B'),array_distinct(string_to_array(@myarray))) THEN 'B'
WHEN array_all(array('B','B'),array_distinct(string_to_array(@myarray))) THEN '...
Re-order your script to bring conditions with duplicated elements ('A's, 'B's, 'C's) down, so that they will not affect other combinations while being evaluated.
WHEN array_all(array_distinct(string_to_array("sumEHZ")), array('A','B')) THEN 'B'
WHEN array_all(array_distinct(string_to_array("sumEHZ")), array('C','A')) ...
The use field calculator, first define a key:value map with matching values for latic/arabic characters. Something like this (here demonstrated with cyrillic characters, as I don't know arabic ones):
a -> а
b -> б
d -> д
Then you can create an array of all the characters of your input strings and for each look ...
This is an older question and the accepted answer was probably correct at the time, however I believe that with new versions of QGIS, (specifically 3.16) an introduction of the overlay_intersection (and overlay_contains/crosses/within/ etc) functions in the expression editor, can allow for spatial queries to be developed within the Field Calculator.
A slightly different approach, converting the characters to its ascii code and adding it as decimals to the house numbers, creating decimal numbers that are then sorted and afterwards coverted back to the initial format: