Self-made distribution maps in QGIS


my goal is to create local self-made distribution maps in QGIS, using my own observations, iNat data and other sources.

I already have imported the spatial frame (TK 25 quadrants) I need and I have created a table for testing purpose. Now my idea was to select frames by occurance of species and export those as a separate shapefile. As there can be multiple species per quadrant and one species can occur in multiple places it has to be a 1:n relationship.

For example:
Tanacetum vulgare occurs in Q 27282 and in Q 27304
Echium vulgare occurs only in Q 27282

With the settings I have set in place I can click on Q 27282 and it will link to the two species that occur there. But right now I don’t know how to do a backwards search (e.g. highlight all places that include Tanacetum vulgare).

Does anyone here have any idea how to solve this problem? Or does anyone know an easier way to create distribution maps? In the test dataset are only a few entries right now. But there can be, of course, thousands of entries when I am ready to import more data.

1 Like

In case you’ve not seen it yet, there’s a helpful post by @pisum on displaying iNat data on GIS maps at Their examples use ArcGIS online but it works just as well in QGIS (use the XYZ Tiles).


i’m assuming:

  1. your TK25 quadrants are expressed as a set of polygons in a vector layer
  2. your occurrences (observations) are expressed as a point layer
  3. you want to effectively turn your TK25 map into a choropleth

generally, there are many ways to accomplish #3 above. if you’re trying to create just a few maps (for just a few taxa), below is the way i would do it. (for a lot of taxa, you’d probably want to find a more efficient and automated way to do it.)

just to illustrate the general process, i’m going to use Rudbeckia amplexicaulis observations (taxon 200073) from an old copy of the AWS Open Data Set for my point layer, and US counties from the US Census Bureau for my vector layer. here, i’ve already loaded these into a new QGIS project:

at this point, i can filter down my point layer, if needed. (for example, if you had many taxa represented, you could filter for just observations of a specific taxon.) in my case, i have just one taxon in my layer, but i see that it includes both non-research-grade observations. (there shouldn’t be any naturally occurring observation out in California.) so i’d like to filter for just research grade.

in the layers pane in the left side of the QGIS window, right click on your point layer, and select Filter… in the Query Builder window, apply the filters you need. in my case, i’ll add "quality_grade" = "research" and then click OK.

that should give me a filtered set of observations (and also note the little filter symbol that now shows up next to my point layer):

now i want to figure out which of my polygons in my vector layer contain the observation points. the easiest way to do this is to use Vector > Analysis Tools > Count Points in Polygon… in the pop-up window, i’ll fill in my polygon layer and my points layer, like so:

clicking on Run will give me a new Count vector layer. it’s basically the same as my original vector layer, except it’ll have an additional NUMPOINTS field that represents the count of points in each polygon.

to visualize the count (NUMPOINTS), you’ll want to right-click on the new layer, and select Properties…, and then go to the Symbology tab. at the top of the tab, you’ll initially see Single Symbol. to do a choropleth, you’ll probably want to select Graduated instead. then in the Value field, select the NUMPOINTS field. select a color ramp. if you just want to show absence/presence, set Mode to Equal Counts, with 2 classes:

that will produce a map that looks like this:

you can also produce a more typical choropleth that shows color variation based on number of observations. for example, Gradated, Mode = Equal Interval, and Classes = 5, with a few custom tweaks to the intervals (in the histogram tab), produces a map like this:

when you have a map you like, you can go to Project > Export, and then export the result as you like.


You always make nice, clear tutorials.

1 Like

Thank you very much.

My problem right now is that a part of my data sources is just a table (.xlsx / .csv). The location can be linked via the TK25 quadrant code, which is included in the table.

Would it be wise to somehow export this table to a point shape before starting the map-building? I thought it would be easier to change the dataset later if it was just a table. In contrary I planned on transforming geodata like iNat datasets to a table that includes the quadrant codes in order to have a similar structure.

I will try to include screenshots later.

just join the data table to your TK25 layer. right click your vector layer, select Properties…, then go to Joins, and add the appropriate joins.

just to illustrate, i created a simple temporary scratch layer that contains notes about different counties. below, i’m adding a join between the County field in that scratch later and the Name field in my US counties layer:

once that’s done, if I look at the Fields tab in the vector layer’s Properties, i’ll see that the table now has a joined Notes field:

… and i can open up the vector layer’s attributes table, and I can see the joined values, too:

… and you’ll be able to use joined field(s) for visualization, as described in my earlier post.

1 Like

Yes, I’ve tried join. But in that case only one species per location is shown.

My example is my home district of Lüneburg. Until now I’ve also included minute fields for more accuracy, but that won’t probably work out due to lack of data.

If I have a dataset with more than one species per location, it does not work out:

That’s why I tried to use relations (via project properties)

In that case I can use the identify tool and it shows me all species that are known for that quadrant:

That is quite helpful. I just don’t know how to select all fields that include a certain species (e.g. Tanacetum vulgare).

Edit: I know it can be done in ArcGIS, but I don’t have access to that program right now.

ok. i changed up my my temporary scratch layer to be modeled more like your data layer:

here, county_code and taxon_id have a M:M relationship. so to see all taxa when when i click on a county, i added the project-level relationship like you did:

but to visualize individual taxa on a map, i still want to start by joining on county code to my vector layer. when i do this, i’ll explicitly make sure i uncheck the “cache join layer in memory” option:

now i’ll set up my vector layer symbology, using the Categorized option on the joined taxon_id field:

initially, it’ll look a little funny, since it can visualize only one taxon per county:

but now i’ll filter for a single taxon on my data layer:

then i’ll refresh the project (F5) to update the map, and it’ll look good for one taxon:

if i undo the filter on my data layer, i’ll still be able to see all taxa associated with a particular selected taxon using the Identify tool:

if you wanted to make this a little fancier, in your data layer you could add a field that will only ever display one value. for example, you could call it present, and set the value to true. then when you join, select only the present field to be associated to the vector table. that way:

  1. when you identify, you won’t see a random taxon_id
  2. you can visualize your symbology on present instead of taxon_id

if you want to be able to filter for an individual taxon for visualization purposes and then still be able to see all associated taxa, you could duplicate your data layer. then join your vector layer to one, and do a project-level relation on the the other.


That works out fine, thank you very much!

With the way you initially proposed I had some problems as QGIS didn’t create symbols for all taxa (as they were hidden in multiple species per location). But with the present field this does not matter anymore.

I have transformed my quadrants to centroids for the present mode. Now I can chose my species through the data table query builder and it will show me the occurances. I have put the symbol size for “all other values” to 0, so they won’t show up on the map:

Again, thank you very much for your help!

edit: or just deactivate the symbol, that’s easier

1 Like

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.