# Calculate the percentage of a Line passing through Polygons

I have a polygon layer of a region (100% coverage, no overlaps) and a line layer in the same region. I want to calculate for each line to which percentage it crosses certain polygons.

I have seen the question also here How to calculate the percentage of a Line through Polygons? but its 6 years old and the proposed solution is completely manual. Is there maybe a newer, more automatable solution, considering QGIS 3.6 or R?

• What have you tried in R already? Have you read your data in? Have you looked at the `sf` package which can do spatial operations such as intersection and overlay etc? Mar 14, 2019 at 8:00

If you just want an outpout list with the result, I would recommend to use a database e.g. PostgreSQL + PostGIS or Spatialite. There you can do it with a simple statement like this:

``````select l.nameofline, p.nameofpolygon,
(st_length(ST_Intersection(l.geom,p.geom)) / st_length(l.geom)) * 100 as linepercentage
from lines l
join polygons p on (st_intersects(l.geom,p.geom));
``````

The output would look like this:

``````Line1    Polygon1   36.0
Line1    Polygon2   64.0
Line2    Polygon1   10.0
Line2    Polygon2   40.0
Line2    Polygon3   50.0
``````

You join the tables "lines" and "polygons" where a line intersects a polygon. For the percentage value the length of the subpart of the line within the specific polygon is divided by the complete length of the origin line and multplied with 100.

• The questioner hasn't mentioned PostGIS and this can be done in R using the `sf` packages. Mar 14, 2019 at 7:59
• looks decent but i dont have any SQL skills, prefer an GIS or R based solution Mar 15, 2019 at 7:08

Get some sample polygons:

``````library(sf)
nc = st_read(system.file("shape/nc.shp", package="sf"))
``````

Next I created some lines as a spatial data frame with an ID for each line.

``````> ld
Simple feature collection with 3 features and 2 fields
geometry type:  LINESTRING
dimension:      XY
bbox:           xmin: -82.45293 ymin: 34.27059 xmax: -77.21339 ymax: 36.51012
epsg (SRID):    4267
proj4string:    +proj=longlat +datum=NAD27 +no_defs
ID                           geom
1  1 LINESTRING (-77.30014 36.39...
2  2 LINESTRING (-82.45293 35.65...
3  3 LINESTRING (-78.72279 34.27...
``````

Now add the length of each line to itself as an attribute:

``````ld\$length = st_length(ld\$geom)
``````

intersect the lines with the polygons. This returns 15 line features, chopped by the polygons:

``````ldnc = st_intersection(ld, nc)
``````

These have the `ID` from the lines, and the attributes from the polygons. Each of these also still has the length from the original source line. So we can compute the percentage this way:

``````ldnc\$lpercent = 100 * (st_length(ldnc)/ldnc\$length)
``````

That gets me a data frame of ID of line, NAME of polygon, and percentage of line ID in polygon NAME (as well as all the other attributes). So I can do:

``````> data.frame(ldnc[,c("ID", "NAME","lpercent")] )
ID        NAME     lpercent                           geom
1     1 Northampton 100.000000 1 LINESTRING (-77.30014 36.39...
2     2    Guilford   5.218371 1 LINESTRING (-79.75943 35.90...
2.1   2     Iredell   6.464218 1 LINESTRING (-80.96068 35.65...
2.2   2       Burke  12.923325 1 LINESTRING (-81.87066 35.72...
2.3   2    McDowell  11.559291 1 LINESTRING (-82.28688 35.67...
2.4   2    Randolph  13.634564 1 LINESTRING (-79.83549 35.50...
2.5   2       Rowan   4.376041 1 LINESTRING (-80.74295 35.57...
2.6   2     Catawba  12.385203 1 LINESTRING (-81.40348 35.70...
2.7   2    Buncombe   4.613577 1 LINESTRING (-82.45293 35.65...
2.8   2    Cabarrus   8.260595 1 LINESTRING (-80.61847 35.50...
2.9   2  Montgomery  10.887982 1 LINESTRING (-80.07517 35.32...
2.10  2      Stanly   9.676922 1 LINESTRING (-80.41298 35.32...
3     3  Cumberland   8.059165 1 LINESTRING (-78.69006 34.84...
3.1   3      Bladen  61.657953 1 LINESTRING (-78.66501 34.45...
3.2   3    Columbus  30.282891 1 LINESTRING (-78.72279 34.27...
``````

line 1 is all in Northampton, line 2 is all over the place, line 3 is mostly Bladen and Columbus with a bit in Cumberland. I can confirm this by plotting and checking.