8

I want to do a statistical analysis. I need to export some features. Their column value between 10%-90% (or 20%-80%) percentile in order to avoid outliers' effect. I can't find a function in the expression window. There are q1, q3, median. They return 25%, 75% and 50% percentile values

There are related posts I found here. None of them meets my need.

How can I export features, their column value is between specific range like 10%-90%, 20%-80% etc?

8

You can create a new function which returns a percentile value, then, compare the field value.

  1. Open Select Feature by Expression tool
  2. Create new function in the Function Editor using the script below. (How to use the Function Editor)
from qgis.core import *
from qgis.gui import *
import numpy as np

values, layer = None, None
@qgsfunction(args='auto', group='Custom')
def percentile(per, layer_name, field_name, feature, parent):
    global layer, values
   
    if values is None:
        layer = QgsProject.instance().mapLayersByName(layer_name)[0]
        values = [f[field_name] for f in layer.getFeatures()]
    
    return float(np.percentile(values, per))
  1. Run this expression to select features whose field value is between 10%-90% percentile. You can change 10 and 90 to change the range.
percentile(10, @layer_name, 'FIELD') < FIELD < percentile(90, @layer_name, 'FIELD')
  • Note: The 3rd parameter (field name) in percentile function must be string -> 'FIELD'. Please read this: Writing an expression
  1. Use Extract selected feature tool.
7

You can use Select by expression and paste this expressions (see also screenshots below):

  1. For the lowest 10%:
"value" <=
array_get(
    array_sort ( 
        array_agg ("value")
    ),
    aggregate (
        @layer, 
        'count', 
        "value"
    ) / 10 - 1
)
  1. For the highest 10%:
"value" >=
array_get(
    array_sort ( 
        array_agg ("value")
    ),
    aggregate (
        @layer, 
        'count', 
        "value"
    ) / 10*9 
)

Combine both expressions with or to the the lowest 10% plus the highest 10% (0-10%, 90-100%).

Screenshot: applying this to a layer with 100 points and an attribute field called value containing random values from 1 to 1000, it will select the lowest 10 (from 100) values entries:

enter image description here

And for the highest values:

enter image description here

And combined:

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.