Convert Spatial Lines to Spatial Polygons - r

Is there an easy way to convert a Spatial Lines into a Spatial Polygon object within R?
Reproducible Example
I have put together a reusable dataset here, which is downloaded from OpenStreetMaps through the overpass package. This extracts the locations of a few airports in South England:
devtools::install_github("hrbrmstr/overpass")
library(overpass)
library(raster)
library(sp)
# Write Query
query_airport <- '
(node["aeroway"="aerodrome"](50.8, -1.6,51.1, -1.1);
way["aeroway"="aerodrome"](50.8, -1.6,51.1, -1.1);
relation["aeroway"="aerodrome"](50.8, -1.6,51.1, -1.1);
);
out body;
>;
out skel qt;
'
# Run query
shp_airports <- overpass::overpass_query(query_airport, quiet = TRUE)
crs(shp_airports) <- CRS("+init=epsg:4326") # Add coordinates
shp_airports <- shp_airports[,1]
# Plot Results
plot(shp_airports, axes = T)
However, the data is of the class "SpatialLinesDataFrame". This really messes things up if you want to do any form of spatial joins or intersections, as it only acknowledges the edge of the region.
Potential Leads
I was exploring the use of SpatialLines2PolySet within the maptools package, but in my time exploring I produced nothing but error codes, so I didn't think there would be any worth including these within the question. There is some guidance about these functions here: https://rdrr.io/rforge/maptools/man/SpatialLines2PolySet.html
Notes
I have searched the web and SO to see find similar questions and struggled to find any questions directly referring to this. A lot seem to reference converting SpatialPoints -> SpatialLineDataFrames , but not SpatialLineDataFrames -> SpatialPolygonDataFrames. This question is similar but lacks any answers (or a reproducible dataset): Close a spatial line into a polygon using a shapefile
In addition, it seems strange that this would be difficult as it is something which can be done so easily in ArcGIS using the "Feature to Polygon" tool. This function requires no additional arguments specified and it works perfectly.

A way to solve the problem would be to use the library sf. After your query
library(sp)
library(raster)
library(sf)
sf_airports <- st_as_sf(shp_airports)
sf_airports_polygons <- st_polygonize(sf_airports)
shp_airports <- as(sf_airports_polygons, "Spatial") # If you want sp
class(shp_airports)

Related

Project SpatialLinesDataFrame for spNetwork

I am trying to use the nkde function of spNetworks to create a KDE of crashes in DC along its roadnetwork. In preparation for the function I am creating lixels for nkde, but running lines_center(lixels) always gives me an error.
lixels <- lixelize_lines(dc_lines,1000,mindist = 250)
samples <- lines_center(lixels)
Whenever I am trying to run lines_center(lixels) I get the following error:
Error in maptools::SpatialLinesMidPoints(with_length) :
is.projected(sldf) is not TRUE
In addition: Warning message:
In RGEOSMiscFunc(spgeom, byid, "rgeos_length") :
Spatial object is not projected; GEOS expects planar coordinates
I tried looking up various techniques, such as turning the SpatialLinesDataFrame into a normal Dataframe, st_as_sf, and then projecting it, but nothing worked out thus far and I always get the same error.
I am loading the data like this:
dc <- readOGR("assessment/test/Roads_2013", "Roads_2013")
Since the uploaded file is a Large SpatialPolygonsDataFrame, I am transforming it into SpatialLines using this code:
dc_lines <- as(dc, "SpatialLinesDataFrame")
Any idea what I am doing wrong or how I can properly project the lines?
The shapefile used is here:
https://opendata.dc.gov/datasets/roads
I am the spNetwork developer. Please, consider posting your issue on the github for faster response. The problem here is that your dataset does not use a planar (X/Y coordinates in meters) CRS, but a geographical one (Lon/Lat in degrees). You need to reproject your data in an appropriate CRS with the function spTransform from sp package. Here is the link with some examples (https://www.rdocumentation.org/packages/rgdal/versions/1.5-28/topics/spTransform-methods).
Maybe the EPSG:2927 could be the CRS to use (I am not familiar with EPSG used in USA).
dc <- readOGR("assessment/test/Roads_2013", "Roads_2013")
dc_proj <- spTransform(dc, CRS("+init=epsg:2927"))

Create Tesselation from SpatialPolygonsDataFrame?

Novice R programmer here... Looking for guidance on building a tess out of the polygons in a SpatialPolygonsDataFrame.
I am invoking quadratcount on points within a state boundary. Rather than using the default grid, I would like to use custom polygons to define the quadrats. Specifically, the county polygons which I have in shapefile format.
I take it from the documentation that the desired tesselation can be created out of a list of 'owin' objects. Where I'm getting jammed up is in taking my SpatialPolygonsDataFrame to generate that list.
I have confirmed that the polygons are read in correctly:
counties <- readOGR('/path/to/counties.shp', layer = "CountyBoundaries", GDAL1_integer64_policy = FALSE)
for(i in 1:nrow(counties)) {
plot(counties[i,])
}
Which generates a series of plots, one per county. That is, of course, only useful to know that my data isn't broken and that I can iterate over the polygons. What I think I need to do is make an owin out of each polygon in the SpatialPolygonsDataFrame and append that to myList for tess(tiles=myList). Not having much success in that approach.
My strong suspicion is that there's an easier way...
Many Thanks,
--gt
Turns out my problem was in not fully understanding how lists are indexed in R. The following bit of code gives me the result I want.
I have no doubt that there is a better, vectorized, way to do it. But in the mean while:
# The point events are in a PPP: StateCrimes_ppp
counties <- readOGR('/path/to/counties.shp', layer = "CountyBoundaries", GDAL1_integer64_policy = FALSE)
tlist <- list()
for(i in 1:nrow(counties)) {
tlist[[i]] <- as(counties[i,], 'owin')
}
QuadCount <- quadratcount(
StateCrimes_ppp,
tess=tess(tiles=tlist)
)
plot(QuadCount, main=NULL)
plot(intensity(QuadCount, image=TRUE), main=NULL, las=1)
If anybody sees how I've taken the long and hard way to solve a simple problem, I'd love to know a better, simpler, more elegant, or more R-like way to do this.
Thanks again,
--gt

Issue with coordinate projection for detecting spatial autocorrelation in R

We have a dataset that contains latitude and longitude coordinates, as well as attribute information, each in its own separate column, stored as numeric. These coordinates have been geocoded based on the geographic coordinate system WGS 1984.
We know that we have significant spatial autocorrelation in our data, which we are hoping to visualize in a bubble plot using the “sp” package. We are modeling our example off of others online, such as here: https://beckmw.wordpress.com/2013/01/07/breaking-the-rules-with-spatial-correlation/ . However, when we try to use the coordinates command within "sp", we keep getting an error message:
Code example:
coords <- data.frame(lead$X, lead$Y)
coordinates(coords) <- c("lead6.X","lead6.Y")
Error in if (nchar(projargs) == 0) projargs <- as.character(NA) missing value where TRUE/FALSE needed
We can't load our direct code because it's sensitive and hosted on a virtual environment without access to the internet. Does anyone have ideas for why this might be happening? We've looked into the proj4 package but can't figure out how to specify a projection system (or is that even the error that we are getting?). If anyone knows of any other packages in R or ways to visualize spatial autocorrelation, those would be much appreciated too.
Your code is a bit "strange": seems you are trying to build a dataset containing only coordinates. AFAIU, you may need something in this line :
data <- data.frame(lead$X, lead$Y, lead$Z)
,with lead$Z corresponding to a generic "variable" you want to inspect, then
coordinates(data) <- c('X','Y')`
proj4string(data) <- "+init=epsg:4326"
, which should give you a proper "SpatialPointsDataframe" with lat-lon WGS84 geographic coordinates (the first line could be also dropped, and you'll keep all variables in the data of the spatialpointsdataframe).
HTH

Autokriging spatial data

I'm trying to use a kriging function to create vertical maps of chemical parameters in an ocean transect, and I'm having a hard time getting started.
My data look like this:
horiz=rep(1:5, 5)
depth=runif(25)
value = horiz+runif(25)/5
df <- data.frame(horiz, depth, value)
The autoKrige function in the automap package looks like it should do the job for me but it takes an object of class SpatialPointsDataFrame. As far as I can tell, the function spTransform in package rgdal creates SpatialPointsDataFrame objects, but there are two problems:
OSX binaries of this aren't available from CRAN, and my copy of RStudio running on OXS 10.7 doesn't seem to be able to install it, and
This function seems to work on lat/long data and correct distance values for the curvature of the Earth. Since I'm dealing with a vertical plane (and short distances, scale of hundreds of meters) I don't want to correct my distances.
There's an excellent discussion of kriging in R here, but due to the issues listed above I don't quite understand how to apply it to my specific problem.
I want a matrix or dataframe describing a grid of points with interpolated values for my chemical parameters, which I can then plot (ideally using ggplot2). I suspect that the solution to my problem is considerably easier than I'm making it out to be.
So there a a few question you want answered:
The spTransform function does not create SPDF's, but transforms between projections. To create a SPDF you can use a simple data.frame as a start. To transform df to a SPDF:
coordinates(df) = c("horiz", "depth")
OS X binaries of rgdal can be found at http://www.kyngchaos.com. But I doubt if you need rgdal.
spTransform can operate on latlong data, but also on projected data. But I do not think you need rgdal, or spTransform, see also point 1.
After you create the SPDF using point 1, you can use the info at the post you mentioned to go on.

Developing Geographic Thematic Maps with R

There are clearly a number of packages in R for all sorts of spatial analysis. That can by seen in the CRAN Task View: Analysis of Spatial Data. These packages are numerous and diverse, but all I want to do is some simple thematic maps. I have data with county and state FIPS codes and I have ESRI shape files of county and state boundaries and the accompanying FIPS codes which allows joining with the data. The shape files could be easily converted to other formats, if needed.
So what's the most straight forward way to create thematic maps with R?
This map looks like it was created with an ESRI Arc product, but this is the type of thing I would like to do with R:
alt text http://www.infousagov.com/images/choro.jpg Map copied from here.
The following code has served me well. Customize it a little and you are done.
(source: eduardoleoni.com)
library(maptools)
substitute your shapefiles here
state.map <- readShapeSpatial("BRASIL.shp")
counties.map <- readShapeSpatial("55mu2500gsd.shp")
## this is the variable we will be plotting
counties.map#data$noise <- rnorm(nrow(counties.map#data))
heatmap function
plot.heat <- function(counties.map,state.map,z,title=NULL,breaks=NULL,reverse=FALSE,cex.legend=1,bw=.2,col.vec=NULL,plot.legend=TRUE) {
##Break down the value variable
if (is.null(breaks)) {
breaks=
seq(
floor(min(counties.map#data[,z],na.rm=TRUE)*10)/10
,
ceiling(max(counties.map#data[,z],na.rm=TRUE)*10)/10
,.1)
}
counties.map#data$zCat <- cut(counties.map#data[,z],breaks,include.lowest=TRUE)
cutpoints <- levels(counties.map#data$zCat)
if (is.null(col.vec)) col.vec <- heat.colors(length(levels(counties.map#data$zCat)))
if (reverse) {
cutpointsColors <- rev(col.vec)
} else {
cutpointsColors <- col.vec
}
levels(counties.map#data$zCat) <- cutpointsColors
plot(counties.map,border=gray(.8), lwd=bw,axes = FALSE, las = 1,col=as.character(counties.map#data$zCat))
if (!is.null(state.map)) {
plot(state.map,add=TRUE,lwd=1)
}
##with(counties.map.c,text(x,y,name,cex=0.75))
if (plot.legend) legend("bottomleft", cutpoints, fill = cutpointsColors,bty="n",title=title,cex=cex.legend)
##title("Cartogram")
}
plot it
plot.heat(counties.map,state.map,z="noise",breaks=c(-Inf,-2,-1,0,1,2,Inf))
Thought I would add some new information here since there has been some activity around this topic since the posting. Here are two great links to "Choropleth Map R Challenge" on the Revolutions blog:
Choropleth Map R Challenge
Choropleth Challenge Results
Hopefully these are useful for people viewing this question.
All the best,
Jay
Check out the packages
library(sp)
library(rgdal)
which are nice for geodata, and
library(RColorBrewer)
is useful for colouring. This map is made with the above packages and this code:
VegMap <- readOGR(".", "VegMapFile")
Veg9<-brewer.pal(9,'Set2')
spplot(VegMap, "Veg", col.regions=Veg9,
+at=c(0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5),
+main='Vegetation map')
"VegMapFile" is a shapefile and "Veg" is the variable displayed. Can probably be done better with a little work. I don`t seem to be allowed to upload image, here is an link to the image:
Take a look at the PBSmapping package (see borh the vignette/manual and the demo) and
this O'Reilly Data Mashups in R article (unfortunately it is not free of charge but it worth 4.99$ to download, according Revolutions blog ).
It is just three lines!
library(maps);
colors = floor(runif(63)*657);
map("state", col = colors, fill = T, resolution = 0)
Done!!
Just change the second line to any vector of 63 elements (each element between 0 and 657, which are members of colors())
Now if you want to get fancy you can write:
library(maps);
library(mapproj);
colors = floor(runif(63)*657);
map("state", col = colors, fill = T, projection = "polyconic", resolution = 0);
The 63 elements represent the 63 regions whose names you can get by running:
map("state")$names;
The R Graphics Gallery has a very similar map which should make for a good starting point. The code is here: www.ai.rug.nl/~hedderik/R/US2004 . You'd need to add a legend with the legend() function.
If you stumble upon this question in the 2020ies, use the magnificent tmap package. It's very simple and straightforward and revolutionized making maps in R. Do not bother to investigate this complicated code.
Check the vignette here.

Resources