Road Length within Polygons in R - r

I have a shape file of a road network and another shape-file containing area boundaries. Is there any better code that I can use to get length of roads that lies inside each polygon?
This Question was asked earlier with the difference that I want to use R instead of QGIS.
I tried:
intersec=intersect(roads,Polygon)
road_length=tapply(intersec$length, intersec$polygon, sum)
This works, but the problem is that the intersection does not divide the length of the roads, that cross to Polygons, but doubles them in the intersec file and assigns the full length of those roads to both Polygons.
How I found out about that Problem: There is no error message, but the following proove tells me that something is wrong:
a=sum(roads$length) and b=sum(intersec$length)
a and b do not have same length -> a is smaller than b.

I actually did this for a project about 8 months ago.
I had been getting into the sf way of dealing with spatial data, and so my solution uses Classes, Methods, and functions from that package.
First, I made sure both my roads and shapes had the same coordinate-reference-system (CRS) by using sf::st_transform on one of them. Then I used sf::st_intersection() to find the intersections, and used sf::st_length() on the result to get the lengths. You may need to aggregate the lengths at this point, depending on whether your roads were combined into one super-multi-line or if each road is its own object. The following gives the gist of what I think ought to work:
sf::st_intersection(road, shape) %>% # Find the intersections, which should all be points or multilines
dplyr::mutate(len_m = sf::st_length(geom)) %>% # Find the length of each line
dplyr::group_by(SHAPE_COLUMNS) %>% # Here you need to insert all the columns from your shapes
dplyr::summarize(len_m = sum(len_m))

Related

sf::st_intersection: virtually random error action

I have a relatively simple task to accomplish in R: I have two polygon layers, a "patches" layer containing 39 focal polygons and a "landcover" layer containing one multipolygon of the focal landcover type. I need to clip those two layers so that I keep only the extent of the focal landcover type within the focal polygons. Sometimes, this works fine with sf::st_intersection, sometimes this works fine using sf::st_differenceand a "negative" landcover layer (containing the extent of all non-focal landcover types) and sometimes none of both approaches work. At first, I thought that these different behaviors depend on the resulting topography complexitiy, but this does not seem to be the case.
The errors I get are of the form
Error in CPL_geos_op2(op, st_geometry(x), st_geometry(y)) :
Evaluation error: TopologyException: Input geom 1 is invalid: Ring Self-intersection at or near point
4372482.6526834015 5297568.4303682083 at 4372482.6526834015 5297568.4303682083.
so I checked for the land cover polygon and each of the focal polygons using sf:: st_is_simple ('patch') which in all cases yielded TRUE.
Consider these three cases:
The "simple" case, where sf::st_intersection works. An example (the
patch in blue, the land cover in green):
sf::st_intersection (focal_patch, focal_landcover):
The "intermediate" case, where sf::st_intersection does not work
but sf::st_difference can be used as a workaround when the focal
landcover is replaced by the non-focal land-cover. An example (the
patch in blue, the non-focal land cover in red:
sf::st_difference (patch, non-focal_landcover)
The "difficult" case where neither keeping the focal land cover (green) type using sf::st_intersection nor excluding the non-focal land cover type (red) using sf::st_difference work - I get similar errors for both approaches:
I was unable to make a reproducible example, so I hope that it is possible to figure out what happens here from the example images. I could not see any pattern in there so perhaps only someone with deep insights into st_intersection and st_difference can indiciate a solution to this...
The error you are describing is not random; ring self intersection means invalid geometry. You should be able to test for it via sf::st_is_valid().
This error is known to happen when using spatial objects originated in the realm of ESRI products, which use slightly different criteria for validity than OGC realm.
To overcome the issue you have several options:
filter the offending geometry out (via subsetting of your spatial object based on the result of sf::st_is_valid() = leaving only valid geometries in place)
try to correct the geometries via sf::st_make_valid() - note that this may result in altered geometry, and may require installation of {lwgeom} package
apply "magic dust" of a buffer of zero width on your invalid spatial object via sf::st_buffer(your_ object, 0). This hack will force creation of a new geometry, possibly overcoming the errors in the original one.
For more information consider the sf package documentation: https://r-spatial.github.io/sf/reference/valid.html

Mapping how many points are within a radius of every location in R

In R, I am trying to create a choropleth map. I have built a database of businesses, some are part of chains (e.g. McDonalds) and others are independent. I want to calculate how many businesses are within 30km of each point on the map, but treat the different locations of chains as a single business.
For example, if you a point is:
5km from a McDonalds,
10km from Taco Bell
15km from Chick-Fil-A
20km from KFC
25km from McDonalds
35km from Five Guys
The colour will show that there are 4 fast food outlets within 30km.
I am happy to use any R package but I am mostly familiar with tmaps and ggplot2 maps.
At this stage the best approach I can think of is to create polygons for each chain and stack them as transparent layers of the same colour. I don't think this would be very efficient and wouldn't create a very nice looking choropleth.
The other answers I could find were either counting points (e.g https://gis.stackexchange.com/questions/229066/counting-how-many-times-a-point-is-inside-a-set-of-intersecting-polygons-in-r) or for GIS software.
EDIT:
I have managed to create a 30km radius from every location of every chain (using rgeos gIntersection). I now have a series of polygons.
To solve my question the additional thing I need to do is create polygons for where:
Only one polygon covers the area,
Two polygons covers the area,
etc.
To try to visual is this I used the answer from https://gis.stackexchange.com/questions/229066/counting-how-many-times-a-point-is-inside-a-set-of-intersecting-polygons-in-r
In the linked question they are trying to count how many polygons cover the numbered points (the image on the right). What I am trying to do is to create the image on the left, where there are polygons of no overlap (1), two overlapping polygons (2) and so on.
I think what you are trying to accomplish would be best approached using a raster approach rather than a chloropleth. To make a chorlopleth, you define a set of (generally irregular) polygons, summarize something within each polygon, then color the polygons based on the attributes. This would be a good approach if you wanted to say how many fast food resteraunts are within each state or county, or how many fast food joints per capita by state.
From your description, however, you are looking for how many fast food joints within a set radius for all points. This is more of a raster question, since you can represent your data on a regular grid.
The raster package is a good start for working with raster data and works well with the sf package.
You need to determine what density you need to accomplish your goal, then use this to determine the resolution of your raster. Once you've got that you can use raster::rasterize() to summarize your (I'm assuming) point data.
I'm assuming you have an object that has the locations of each restaurant, I'll call this object "points".
library(raster)
library(sf)
# create raster template with 30km resolution (I'm assuming your projection is in meters)
raster_template = raster((extent(points),
resolution = 30000,
crs = st_crs(points)
)
# rasterize your point data
r = rasterize(points, raster_template, fun = "count")
This should create a grid where each cell has the number of points within each 30km cell. You should then be able to plot the raster, but may want to either clip or mask it to just show parts that are within New Zealand

raster:: extract produces an empty list

I am trying to extract the values of pixels in a DSM(CHM) within digitized tree crowns.
first I set my working directory read in the shapefile and raster.
TreeCrowns <-shapefile("plot1sag_shape/plot1sag.shp")
CHM <- raster('272280split4.tif')
Then I try to extract the pixel values
pixel <- raster::extract(CHM, TreeCrowns, method= 'simple', weights=FALSE, fun=NULL)
But I get an empty list with all NULL values for every polygon. I have confirmed that the CHM and polygons are in the same location. What can I do to fix this?
Since your shapefile consists of polygon, the extract() function need to know how to summarise the pixel values across a polygon via the fun= argument. Since you provide fun=NULL, the function interpret as returning NULL values to summarise the pixel values.
Try fun=mean or fun=sum (and they mean different thing so see which one suits you).
That probably happens because the polygons and the raster do not overlap. Can you show(CHM) and TreeCrowns? Have you looked at
plot(CHM)
lines(TreeCrowns)
Or are your polygons very small relative to the raster cells? In that case try argument small=TRUE

r alphahull post-processing/ avoid two hulls

I have got a table with coordinates of points and want to get the smalest polygon around them. I tried different functions and so far alphahull works best for my purposes. My major interest is in the area of the hull. I have got approximately 3500 datasets, so I have to find a reliable method for my analysis.
I analysed some datasets and realised that in some cases I get a hull in a hull and areahull() is not able to return an area. A higher alpha-value would avoid this but would overestimate my area by far.
Is there a possibility to post-process my alpha-hull to remove the second hull? Or a better method to get the size of the area?
library(alphahull)
tmp <- ahull(path.points.1$x, path.points.1$y, alpha = 50)
plot(tmp, wpoints = F)
lin to example dataset
I found a solution which seems to work for my purposes: the function ahull_track() returns only the boundary as a geom_path()-object. the coordinates of the single boundary segments are stored in a list. unfortunately they are not in the correct order, so it is no straight-forward solution. I had to write a function which rearranges the segments into the correct order and generates a polygon.

R: Determining whether a point lies inside a region made up of separate polygons generated from contourLines()

I am using the function contourLines() in R to record the vertices of a contour based on a probability density estimation. Then I test to see whether a point lies inside the contour region. I can do this test easily when there is only one region (polygon) created from contourLines, but sometimes the there are multiple polygons created. I am trying to come up with a way to determine whether a point lies inside the multiple polygon contour.
My idea so far is to calculate the number of polygons generated and treat each one separately. I was thinking I could use graph theory to determine the number of polygons generated because there will not be a path between points on 2 separate polygons.
Probably there is an easier way. Any suggestions?
Thanks in advance,
HS

Resources