Overlay shapefile over Raster in Multiple plots - r

I am trying overlay the shapefile of south asia on top of multiple raster plots using the code as below: 'a' is a multilayered raster file. Here is the link to the data (917KB size) Test_Data
ras <- list.files("/filepath/", pattern = "\\.tif$", full=TRUE)
s <- stack(ras)
south_asia <- readOGR('/filepath/south_asia.shp') #to import shapefile
cropped <- crop(x = s, y = extent(south_asia)) #crop raster
plot(cropped)
plot(south_asia, add=TRUE)
This code gives me one shapefile and multiple raster plots. How do i overlay the shapefile on top of the rasters?
Any help will be appreciated.
P.S: They are in same CRS
Thanks

First, please try to give a reproducible example instead of a link to download files externally!
If you manually construct the plot (e.g. using par with base plotting) you can get your desired behaviour:
library(raster)
## testdata
# shapefile
shp <- getData(country='IND', level=1)
# raster
r <- getData('alt', country='IND', mask=TRUE)
# create 4 layer rasterstack
rs <- stack(r,r,r,r)
## finally plot
# 2 rows, 2 cols
par(mfrow=c(2,2))
# loop layers
for (ii in 1:nlayers(rs)){
plot(subset(rs,ii), main=names(rs)[ii])
plot(shp, add=T)
}
Edit:
Use plot(subset(rs,ii), main=names(rs)[ii]) in the loop to plot the respective layer.
The result:

I would suggest using the argument addfun in the plot option for raster stack/brick
For example:
# Function to add shapefile "shp_file" on each raster plot
add_shp=function(){plot(shp_file, bg="transparent", add=TRUE)}
#Plot selected raster of a raster stack, rs
plot(rs[[c(1:5)]],col=tim.colors(5),addfun=add_shp)
This will add shapefile shp_file to each of the 5 plots from the rasterstack rs.

Related

Convert a column value(s) in SpatialpolygonDataframe into raster image

I need help with converting a variable or column values in a spatial polygon into a raster image. I have spatial data of administrative units with income(mean) information for each unit. I want to convert this information into raster for further analysis.
I tried the code below but it didn't work.
r <- raster(ncol=5,nrow=15)
r.inc <- rasterize(DK,r,field=DK#data[,2],fun=mean)
Where SP is the spatial polygon and the mean income for each spatial unit stored in column 2 of the SpatialPolygonDataframe. Can anyone help with a function or code of how to rasterise the values in the column of interest? An example of the spatialpolygondataframe (created) and my attempt to rasterize the data are below
suppressPackageStartupMessages(library(tidyverse))
url = "https://api.dataforsyningen.dk/landsdele?format=geojson"
geofile = tempfile()
download.file(url, geofile)
DK <- rgdal::readOGR(geofile)
DK#data = subset(DK#data, select = c(navn))
DK#data$inc = runif(11, min=5000, max=80000)
require(raster)
r <- raster(ncol=5,nrow=15)
r.inc <- rasterize(DK,r,field=DK#data[,2],fun=mean)
plot(r.inc)
Thank you.
Acknowledgement: The code for creating the sample SPDF was sourced from Mikkel Freltoft Krogsholm (link below).
https://www.linkedin.com/pulse/easy-maps-denmark-r-mikkel-freltoft-krogsholm/?trk=read_related_article-card_title
Here's something that makes a raster.
library(tidyverse)
library(rgdal)
library(raster)
url <- "https://api.dataforsyningen.dk/landsdele?format=geojson"
geofile <- tempfile()
download.file(url, geofile)
DK <- rgdal::readOGR(geofile)
r_dk <- raster(DK, nrows = 100, ncols = 100) # Make a raster of the same size as the spatial polygon with many cells
DK$inc <- runif(nrow(DK), min=5000, max=80000) # Add some fake income data
rr <- rasterize(DK, r_dk, field='inc') # Rasterize the polygon into the raster - fun = 'mean' won't make any difference
plot(rr)
The original raster was the size of the whole Earth so I think Denmark was being averaged to nothing. I resolved this by making an empty raster based on the extent of the DK spatial polygons with 100x100 cells. I also simplified the code. Generally, if you find yourself using # with spatial data manipulation, it's a sign that there might be a simpler way. Because the resolution of the raster is much larger than the size of each DK region, taking the average doesn't make much difference.

Plotting a raster with recentered Mollweide projection in R

I would like to generate a map of the world in Mollweide projection, but centered on longitude 150. I would like to plot a raster and a vector map of the world on top.
library(maptools)
library(raster)
library(rgdal)
# generate some dummy data
data(wrld_simpl)
ras <- raster(ext=extent(wrld_simpl), res=c(2,2))
values(ras) <- runif(ncell(ras))
ras <- mask(ras, wrld_simpl, inverse=TRUE)
# Here is the map unprojected, without recentering
plot(ras)
plot(wrld_simpl, add=TRUE, col='black')
# now I transform to Mollweide
mollproj <- '+proj=moll +lon_0=150 +ellps=WGS84'
# project raster
ext <- projectExtent(ras, mollproj)
rasMoll <- projectRaster(ras, to=ext)
# project vector map
wrldMoll <- spTransform(wrld_simpl, CRS(mollproj))
# plot
plot(rasMoll)
plot(wrldMoll, add=TRUE)
There are several problems here. The map is not at full extent, the vector map has horizontal lines, and there are floating pieces of the raster beyond the bounds of the world.
Any suggestions on how to get this to work?
Thanks!

How to get polygons of a shapefile containing centroids of polygons from another shapefile in R?

I'm working with two shapefiles in R and I'm trying to select the polygons of one of them which contains the centroids of another shp.
I've been able to get the centroids of each file separately (attached image), but I can't find a way to accomplish the task described above. In the example, let's say I want to get only polygons (shp1) with blue centroids (from shp2) inside of them.
example
Thanks!
You could use gCentroid() and gContains() from the rgeos package:
library(raster) ## For data and functions used to make example SpatialPolygons objects
library(rgeos) ## For topological operations on geometries
## Make a couple of example SpatialPolygons objects, p1 & p2
p1 <- shapefile(system.file("external/lux.shp", package="raster"))
r <- raster(extent(p1))
r[] <- 1:10
p2 <- rasterToPolygons(r, dissolve=TRUE)
## Find centroids of p2
cc <- gCentroid(p2, byid=TRUE)
## Select Polygons in p1 that contain at least one of centroids from p2
p3 <- p1[apply(gContains(p1, cc, byid=TRUE), 2, any),]
## Plot to check that that worked
ared <- adjustcolor("red", alpha=0.6)
plot(p1)
plot(p3, add=TRUE, col="wheat")
plot(p2, add=TRUE, border=ared)
points(cc, pch=16, col=ared)

Plot spatial area defined by multiple polygons

I have a SpatialPolygonsDataFrame with 11589 spatial objects of class "polygons". 10699 of those objects consists of exactly 1 polygon. However, the rest of those spatial objects consist of multiple polygons (2 to 22).
If an object of consists of multiple polygons, three scenarios are possible:
1) The additional polygons could describe a "hole" in the spatial area described by the first polygon .
2) The additional polygons could also describe additional geographic areas, i.e. the shape of the region is quite complex and described by putting together multiple parts.
3) Often it is a mix of both, 1) and 2).
My question is: How to plot such a spatial object which is based on multiple polygons?
I have been able to extract and plot the information of the first polygon, but I have not figured out how plot all polygons of such a complex spatial object at once.
Below you find my code. The problem is the 15th last line.
# Load packages
# ---------------------------------------------------------------------------
library(maptools)
library(rgdal)
library(ggmap)
library(rgeos)
# Get data
# ---------------------------------------------------------------------------
# Download shape information from the internet
URL <- "http://www.geodatenzentrum.de/auftrag1/archiv/vektor/vg250_ebenen/2012/vg250_2012-01-01.utm32s.shape.ebenen.zip"
td <- tempdir()
setwd(td)
temp <- tempfile(fileext = ".zip")
download.file(URL, temp)
unzip(temp)
# Get shape file
shp <- file.path(tempdir(),"vg250_0101.utm32s.shape.ebenen/vg250_ebenen/vg250_gem.shp")
# Read in shape file
x <- readShapeSpatial(shp, proj4string = CRS("+init=epsg:25832"))
# Transform the geocoding from UTM to Longitude/Latitude
x <- spTransform(x, CRS("+proj=longlat +datum=WGS84"))
# Extract relevant information
att <- attributes(x)
Poly <- att$polygons
# Pick an geographic area which consists of multiple polygons
# ---------------------------------------------------------------------------
# Output a frequency table of areas with N polygons
order.of.polygons.in.shp <- sapply(x#polygons, function(x) x#plotOrder)
length.vector <- unlist(lapply(order.of.polygons.in.shp, length))
table(length.vector)
# Get geographic area with the most polygons
polygon.with.max.polygons <- which(length.vector==max(length.vector))
# Check polygon
# x#polygons[polygon.with.max.polygons]
# Get shape for the geographic area with the most polygons
### HERE IS THE PROBLEM ###
### ONLY information for the first polygon is extracted ###
Poly.coords <- data.frame(slot(Poly[[polygon.with.max.polygons ]]#Polygons[[1]], "coords"))
# Plot
# ---------------------------------------------------------------------------
## Calculate centroid for the first polygon of the specified area
coordinates(Poly.coords) <- ~X1+X2
proj4string(Poly.coords) <- CRS("+proj=longlat +datum=WGS84")
center <- gCentroid(Poly.coords)
# Download a map which is centered around this centroid
al1 = get_map(location = c(lon=center#coords[1], lat=center#coords[2]), zoom = 10, maptype = 'roadmap')
# Plot map
ggmap(al1) +
geom_path(data=as.data.frame(Poly.coords), aes(x=X1, y=X2))
I may be misinterpreting your question, but it's possible that you are making this much harder than necessary.
(Note: I had trouble dealing with the .zip file in R, so I just downloaded and unzipped it in the OS).
library(rgdal)
library(ggplot2)
setwd("< directory with shapefiles >")
map <- readOGR(dsn=".", layer="vg250_gem", p4s="+init=epsg:25832")
map <- spTransform(map, CRS("+proj=longlat +datum=WGS84"))
nPolys <- sapply(map#polygons, function(x)length(x#Polygons))
region <- map[which(nPolys==max(nPolys)),]
plot(region, col="lightgreen")
# using ggplot...
region.df <- fortify(region)
ggplot(region.df, aes(x=long,y=lat,group=group))+
geom_polygon(fill="lightgreen")+
geom_path(colour="grey50")+
coord_fixed()
Note that ggplot does not deal with the holes properly: geom_path(...) works fine, but geom_polygon(...) fills the holes. I've had this problem before (see this question), and based on the lack of response it may be a bug in ggplot. Since you are not using geom_polygon(...), this does not affect you...
In your code above, you would replace the line:
ggmap(al1) + geom_path(data=as.data.frame(Poly.coords), aes(x=X1, y=X2))
with:
ggmap(al1) + geom_path(data=region.df, aes(x=long,y=lat,group=group))

Is it possible to overlay SpatialLinesDataFrame and SpatialPolygonDataFrame

I am wondering if this is possible to do this R .
I have one data as SpatialLinesDataFrame and another as spatialPolygonDataFrame. Is it possible to overlay these two data ?
When I try to overlay these I get the following error:
jd <- overlay(res,hello)
Error in function (classes, fdef, mtable) : unable to find an inherited method for function
‘overlay’ for signature ‘"SpatialLinesDataFrame", "SpatialPolygonsDataFrame"’
In the above code res is the SpatialLinesDataFrame and hello is SpatialPolygonDataFrame.
I have an shapefile and then I have data points with x,yand z
coordinates. I want to show the contour lines on the shapefile.
The procedure I used is using akima package to do the interpolation. The
code I used to interpolate is
fld <- interp(x,y,z)
Then I changed this to spatial object by using following code:
res <-ContourLines2SLDF(contourLines(fld))
The above command would store the contourlines as spatial data.
Then I read the shapefile and I plot both shapefile and res as follows:
p1 <-
spplot(hello,sp.layout=list(list("sp.lines",res)),col="blue",lwd=0,fill="grey",colorkey=F)
p1
"hello" is my shapefile and "res" is the object I created as shown above.
The problem is contour stored in "res" extends beyond the shapefile. So I
want to clip that contour with the shapefile and only display the contour
within the shapefile area.
So I am looking for a way to clip the contour layer with the polygon layer.
I have attached the image I got with my code.
In the image you can see the lines out of the shapefile. I also want to know
how can I display the contour levels on the map.
Thank you so much.
Jdbaba
I also want to know what does overlay does exactly. Does it intersect the area of both the data ?
Thank you.
It sounds like you're trying to clip your lines to the polygon extent. Use gIntersection from the rgeos package. Here's a reproducible example:
library(rgeos)
xx <- SpatialPoints(coords=matrix(data=c(0,0), nrow=1))
xx <- gBuffer(spgeom=xx, width=1)
yy <- SpatialLines(list(Lines(Line(matrix(c(-1,1,-1,1), nrow=2)), ID=1)))
zz <- gIntersection(yy, xx)
You can overlay the plot like so:
plot(xx)
plot(zz, add = TRUE, col = "blue")
Noah's answer has worked quite well for me. However, the output of his answer is a SpatialLines object, which cannot be saved as a shape file.
My two cents here is about how you can convert your SpatialLines object into a SpatialLinesDataFrame and save it as a shape file.
res.df <- fortify(res) # create data frame of res, your original SpatialLinesDataFrame
data <- data.frame(id = unique(res.df$id)) # get ids of road segments
rownames(data) <- data$id
# transform SpatialLines object into SpatialLinesDataFrame
zzSpatialLineDF <- SpatialLinesDataFrame(zz, data) # convert zz object keeping road ids
# 5 Save Shape File to your working directory
writeOGR(zzSpatialLineDF, dsn = '.', layer ='zzSpatialLineDF', driver = 'ESRI Shapefile')

Resources