QGIS Percentile Class Breaks – Creating with numpy.percentile

numpypyqgisstyle

I am having trouble making percentile breaks in my point data for a numeric field.

I have looked at these similar questions, most seem to relate to raster though:

I want breaks at 25, 50, 75, 90, 95, and 98 percentiles. Here is my code:

case
    when ag_ppm <= q1(ag_ppm)
        then '< 25th: ' || minimum("ag_ppm") || ' - ' || q1(ag_ppm)
    when ag_ppm < median(ag_ppm) AND ag_ppm > q1(ag_ppm)
        then '25th to 50th: ' || (q1(ag_ppm)+0.001) || ' - ' || median(ag_ppm)
    when ag_ppm <= q3(ag_ppm) AND ag_ppm > median(ag_ppm)
        then '50th to 75th: ' || (median(ag_ppm)+0.001) || ' - ' || q3(ag_ppm)
    when ag_ppm <= percentile(90,ag_ppm) AND ag_ppm > q3(ag_ppm)
        then '75th to 90th: ' || (q3(ag_ppm)+0.001) || ' - ' || percentile(90,ag_ppm)
    when ag_ppm <= percentile(95,ag_ppm) AND ag_ppm > percentile(90,ag_ppm)
        then '90th to 95th: ' || (percentile(90,ag_ppm)+0.001) || ' - ' || percentile(95,ag_ppm)
    when ag_ppm <= percentile(98,ag_ppm) AND ag_ppm > percentile(95,ag_ppm)
        then '95th to 98th: ' || (percentile(95,ag_ppm)+0.001) || ' - ' || percentile(98,ag_ppm)
    when ag_ppm <= max(ag_ppm) AND ag_ppm > percentile(98,ag_ppm)
        then '> 98th: ' || (q3(ag_ppm)+0.001) || ' - ' || maximum(ag_ppm)
    else 'NULL'
end

Here is my code to create a percentile function in QGIS:

from qgis.core import *
from qgis.gui import *
import numpy as np

@qgsfunction(args='auto', group='Custom')
def percentile(per, field_name, feature, parent):
    return float(np.percentile(np.array(field_name), per))

However, when I run this it gives me numerous results for the percentile function. I think I need to add a group by clause in my code but not sure how.

enter image description here

Best Answer

UPDATE: all I needed to do was change array(ag_ppm) to array_agg(ag_ppm, project) since there is only 1 project shown at a time.

see code below:

case
    when ag_ppm <= q1(ag_ppm)
        then '<25th: ' || minimum("ag_ppm") || ' - ' || q1(ag_ppm)
    when ag_ppm < median(ag_ppm) AND ag_ppm > q1(ag_ppm)
        then '25th to 50th: ' || (q1(ag_ppm)+0.001) || ' - ' || median(ag_ppm)
    when ag_ppm <= q3(ag_ppm) AND ag_ppm > median(ag_ppm)
        then '50th to 75th: ' || (median(ag_ppm)+0.001) || ' - ' || q3(ag_ppm)
    when ag_ppm <= percentile(90,array_agg(ag_ppm,project)) AND ag_ppm > q3(ag_ppm)
        then '75th to 90th: ' || (q3(ag_ppm)+0.001) || ' - ' || percentile(90,array_agg(ag_ppm,project))
    when ag_ppm <= percentile(95,array_agg(ag_ppm,project)) AND ag_ppm > percentile(90,ag_ppm)
        then '90th to 95th: ' || (percentile(90,array_agg(ag_ppm,project))+0.001) || ' - ' || percentile(95,array_agg(ag_ppm,project))
    when ag_ppm <= percentile(98,ag_ppm) AND ag_ppm > percentile(95,ag_ppm)
        then '95th to 98th: ' || (percentile(95,array_agg(ag_ppm,project))+0.001) || ' - ' || percentile(98,array_agg(ag_ppm,project))
    when ag_ppm <= maximum(ag_ppm) AND ag_ppm > percentile(98,array_agg(ag_ppm,project))
        then '>98th: ' || (percentile(98,array_agg(ag_ppm,project))+0.001) || ' - ' || maximum(ag_ppm)
    else 'NULL'
end
Related Question