QGIS Symbology – Display more symbols for each point depending on attribute numeric value

attribute-tabledisplayfields-attributesqgissymbology

I have a point feature layer with some attributes. The numeric value of each attribute stands for the number of items of that attribute related to each point.
Is it possible in QGIS to display a symbology according to these values, where the number of symbols depends on the numeric value itself?

For example, with an attribute table like this:

pt_number apples bananas
1 1 2
2 3 1

the symbology for point 1 would be this:

enter image description here

I would like to avoid to create as many rules as the possible combinations, just to set the main icons and then display them automatically.

Best Answer

You can use the Geometry Generator in the Layer Style definition.

With one Geometry Generator entry for each relevant category.

These will be used to generate:

  • "Bananas" points, starting from $geometry, spaced by a given amount;
  • "Apples" points, starting from where Bananas left us with;
  • "Oranges" points, starting from where Apples + Bananas left us with;

The generic code will be: collect_geometries(array_foreach(generate_series(0,number_items-1,1),translate($geometry,@element*0.005,0)))

generate_series(0,number_items-1,1) to get the number of items;

translate($geometry,@element*0.005,0) to generate points right from the initial $geometry. 0.005 is the horizontal spacing, 0 the vertical spacing. Alternatives can be used to pile symbols instead of aligning them.

collect_geometries(array_foreach(...)) to generate multipart geometry for the array of translated points


Results with the following sample data:

pt_number bananas apples oranges
1 1 2 2
2 3 1 0
3 4 0 4
4 0 1 0

enter image description here


Settings the Style for 3 item categories:

In the Layer Style, use the 3 separate levels of Geometry Generator:

The first one: enter image description here

The code for each of the 3 levels:

case when "Bananas" >0 then 
collect_geometries(array_foreach(
generate_series(0,"Bananas"-1,1),
translate($geometry,@element*0.005,0)))
end

then:

collect_geometries(array_foreach(
generate_series(0,"Apples"-1,1),
translate($geometry,@element*0.005+"Bananas"*0.005,0))) 

(note the offset by number of Bananas)

and then:

collect_geometries(array_foreach(
generate_series(0,"Oranges"-1,1),
translate($geometry,@element*0.005+("Bananas"+"Apples")*0.005,0)))

(note the offset by number of Bananas + number of Apples)

enter image description here


Alternate styling :

That's the baseline that should allow you to customize your Symbols. For something that matches your initial representation even more closely, you can do the following (keep the Simple Marker for the Point geometry + add one offset in X and Y direction in the translate

enter image description here

Related Question