6

I usually calculate total line length by adding a $length field and going to summary statistics. How would I do this if I have many layers? Is there a faster way? I batch added the $length to all of them.

Given a table of contents [Layer 1, Layer 2, Layer... ...Layer 100], how do I end up with a table of the form [[Layer 1: Total Length 10123, Layer 2: 2349 ...]?

1
  • 3
    Sounds like a Python task...Would be Python a possible way to go for you?
    – eurojam
    Aug 24, 2021 at 4:45

3 Answers 3

8

Use PyQGIS:

#Create an empty table in memory and add fields
newtable = QgsVectorLayer("None", "Results", "memory")
provider = newtable.dataProvider()
provider.addAttributes([QgsField('Layername', QVariant.String),
        QgsField('Length', QVariant.Double)])
newtable.updateFields()

#For each table added to the map calculate length and 
#  add layername and length to the created table
for lyr in QgsProject.instance().mapLayers().values():
    f = QgsFeature()
    total_length = sum([r.geometry().length() for r in lyr.getFeatures()]) #Possible to round decimals here
    f.setAttributes([lyr.name(), total_length])
    provider.addFeature(f)
    
QgsProject.instance().addMapLayer(newtable)

enter image description here

4

This solution is working (as long you not tired to repeat the pattern) but not as efficient as one suggested by @BERA

There is a possibility using a "Virtual Layer" through Layer > Add Layer > Add/Edit Virtual Layer...

Let's assume there are polyline layers called 'lines_test' and 'lines_test2'.

input

With the following query, it is possible to end up with a table of lengths for all polyline layers.

SELECT "lines_test" AS Layer,
       COUNT(*) Features,
       round(SUM(ST_length(geometry)), 6) AS Sumlength
FROM "lines_test"
UNION
SELECT "lines_test2" AS Layer,
       COUNT(*) Features,
       round(SUM(ST_length(geometry)), 6) AS Sumlength
FROM "lines_test2"

The output attribute table will look like

output

The above query embrace the following pattern:

SELECT "layername1" AS Layer,
       COUNT(*) Features,
       round(SUM(ST_length(geometry)), 6) AS Sumlength
FROM "layername1"
UNION
SELECT "layername2" AS Layer,
       COUNT(*) Features,
       round(SUM(ST_length(geometry)), 6) AS Sumlength
FROM "layername2"
UNION
...
UNION
SELECT "layernameN" AS Layer,
       COUNT(*) Features,
       round(SUM(ST_length(geometry)), 6) AS Sumlength
FROM "layernameN"
3

You can easily create the sum of the length of all lines of all layers using this expression based on the variable @layer_ids (=List of all map layer IDs from the current project). Be aware: array_sum is available since QGIS 3.18):

array_sum (
    array_foreach (
        @layer_ids,
        aggregate( 
            @element, 
            'sum',
            $length
)))

If you have only line-layers in your project, this is enough. If you have other layers that should be ignored, you must exclude them. To consider only layers of the type Line, thus excluding point, polygon and raster layers, use this expression (tribute for the array_filter-part to this solution):

array_sum (
    array_foreach (
        array_filter (
            @layer_ids,
            layer_property( 
                @element, 
                'geometry_type'
            )='Line'
        ),
        aggregate( 
            @element, 
            'sum',
            $length)))

Screenshot: summing up the length of all lines of all layers with the expression: enter image description here

Screenshot: the expression in action, taking into consideration only line-layers, ignoring all others (like point, polygon or raster layers etc.):

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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