R Levelplot overlaying two SpatialPolygonsDataFrame on a RasterLayer projection - r

posted also on gis.stackexchange
I'm having some trouble plotting a RasterLayer and a SpatialPolygonsDataFrame in a level plot in R. Something is wrong with the projection, but I don't understand what.
Here you can find my
reproducible example data and code:
library(sp)
library(rgdal)
library(rgeos)
library(raster)
library(rasterVis)
library(maptools)
setwd("C:/...path_to/test2")
data<-read.csv("test.csv", header=TRUE)
#creating the raster from a data.frame and giving projection
raster<-rasterFromXYZ(data, crs="+proj=longlat")
raster_proj<-projectRaster(raster, crs="+proj=longlat +datum=WGS84
+ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs")
#loading shapes
nuts<-readShapePoly("NUTS_RG_WGS84.shp", proj4string=CRS("+proj=longlat"))
countries<-readShapePoly("countries.shp", proj4string=CRS("+proj=longlat"))
#subsetting the raster
raster_clip<- crop(raster_proj, countries, snap="near")
#plot
p.strip <- list(cex=1.5, lines=1, fontface='bold')
x.scale <- list(cex=1.5)
y.scale <- list(cex=1.5)
label <- list(labels=list(width=1, cex=1.5), height=0.95)
levelplot(raster_clip, par.settings = RdBuTheme, margin=FALSE,
at=seq(min(na.omit(values(raster_clip))), max(na.omit(values(raster_clip))), length.out=15),scales=list(x=x.scale, y=y.scale),
par.strip.text=p.strip, colorkey=label, xlab=list(label="Longitude", cex=2), ylab=list(label="Latitude", cex=2))+
layer(sp.polygons(nuts))+layer(sp.polygons(countries))
The error message is:
Error: Attempted to create layer with no geom.
But the raster and the polygons are in the same projection. I also tried to re-project the polygons using:
nuts <- spTransform(nuts, CRS("+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs"))
countries <- spTransform(countries, CRS("+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs"))
Any Idea?

If you don't want to or can't detach ggplot2 because you need it for something else, you can also call the layer function specifically from the latticeExtra package using:
levelplot(myRaster) +
latticeExtra::layer(sp.polygon(myPolygon))

detach("package:ggplot2", unload=TRUE)

I solved this problem by detaching ggplot2 from my library.

Related

How to change the projection of a map (created from ETOPO1 bathymetry data) in R

I have downloaded a TIF file from the ETOPO1 website, which contains bathymetry information. I have plotted the bathymetry map using the following code:
bathy <- raster("ice_data.tif")
plot(bathy)
bathy[bathy>0] <-0
dev.new()
plot(bathy)
intervals<-c(-0.000001, -500, -1000, -5000)
colourscale<-colorRampPalette(c("blue","lightblue1"))
plot(bathy, breaks=intervals, col = colourscale(4))
I am wanting to change the project of the map (to this: +proj=laea +lon_0=-21.09375 +lat_0=-90 +datum=WGS84 +units=m +no_defs). I have tried using the code below (with st_transform() function), but am getting an error message
Error in UseMethod("st_transform") : no applicable method for 'st_transform' applied to an object of class "c('RasterLayer', 'Raster', 'BasicRaster')
new_map = st_transform(bathy, crs = "+proj=laea +lon_0=-21.09375 +lat_0=-90 +datum=WGS84 +units=m +no_defs")
Has anyone got any suggestions? It would be very much appreciated!
Thanks
For rasters you need to use the raster::crs() function to change the crs.
The sf::st_transform() function needs an sf object as input.
Try:
new_crs <- "+proj=laea +lon_0=-21.09375 +lat_0=-90 +datum=WGS84 +units=m +no_defs"
crs(bathy) <- new_crs

R and Export raster extent as esri shapefile

I am working with a raster dataset in R and would like to make a polygon of its extent and then export this as an ESRI shapefile. My problem, or at least what I think is the problem, occurs when I try to export the spatial polygon dataframe as I get the following error:
Error in writeOGR(p, ".", "xyz_extent", driver="ESRI Shapefile") :
obj must be a SpatialPointsDataFrame, SpatialLinesDataFrame or
SpatialPolygonsDataFrame
My script follows. Please note, I have a beginner skillset when working with spatial data in R so I do ask that answers be well described. Thank you in advance to those that chime in.
Script:
library(raster)
xyz <- raster("xyz.asc")
crs(xyz)
# CRS arguments: +proj=tmerc +lat_0=0 +lon_0=-115 +k=0.9992 +x_0=500000 +y_0=0 +datum=NAD83 +units=m +no_defs +ellps=GRS80 +towgs84=0,0,0
e <- extent(xyz)
p <- as(e, 'SpatialPolygons')
crs(p) <- crs(xyz)
library(rgdal)
writeOGR(p, ".", "xyz_extent", driver="ESRI Shapefile")
The error occurs because you have a SpatialPolygons, not a SpatialPolygonsDataFrame object. An easy way around this is to use the shapefile function instead.
library(raster)
xyz <- raster()
e <- extent(xyz)
p <- as(e, 'SpatialPolygons')
crs(p) <- crs(xyz)
shapefile(p, "xyz_extent.shp")
And you can read the file again with the same function
x <- shapefile("xyz_extent.shp")

Plotting a shapefile on a raster layer in R

I want to plot a raster layer with points from a shapefile on top.
I have checked previous answers on this, but i still have a problem.
I can plot the point shapefile and the raster layer separately without problem, but not together.
As far as I can see they should be in same projection and location.
require(maptools)
myproj <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
shape <- readShapeSpatial("directory/mypoints.shp", proj4string = CRS(myproj))
plot(r <- raster(listVI[200]))
plot(shape)
I found the answer, I will put it here for others who may encounter same problem.
The solution is simply: (as long as raster and shapefile is in same CRS)
plot(r)
plot(shape, add = TRUE)

How to plot a specific column from a SpatialPolygonDataframe with leafletR?

I would like to create a choropleth map using leafletR::leaflet.
My data comes in a SpatialPolygonsDataFrame, and I would like to choose a specific column to be plotted.
With sp::spplot, this is easy-peasy, since the argument zcol allows me to specify the layer/column to be plotted:
library("maptools");library("sp");library("leafletR")
SP <- readShapePoly(system.file("shapes/sids.shp",
package="maptools")[1],
proj4string=CRS("+proj=longlat +datum=WGS84
+no_defs +ellps=WGS84
+towgs84=0,0,0"))
spplot(SP, zcol="BIR79")
However, with leafletR, I don't know how to specify the layer, and it just plots the plain map borders:
SP4leaflet <- toGeoJSON(data=SP, dest=tempdir(), name="BIR79")
SPleaflet <- leaflet(data=SP4leaflet, dest=tempdir(),
title="Trying to plot BIR79",
base.map="osm", popup="*")
SPleaflet
Any ideas on how to select the desired layer/column to be plotted with leafletR?
For the sake of completeness, I would like to mention that this is now easily possible using library(mapview).
library("maptools")
library("sp")
library("mapview")
SP <- readShapePoly(system.file("shapes/sids.shp",
package="maptools")[1],
proj4string=CRS("+proj=longlat +datum=WGS84
+no_defs +ellps=WGS84
+towgs84=0,0,0"))
spplot(SP, zcol="BIR79")
mapview(SP, zcol="BIR79")
See also http://edzer.github.io/sp/#interactive-maps-leaflet-mapview for a similar example and http://environmentalinformatics-marburg.github.io/web-presentations/20150723_mapView.html for more functionality of mapview.
Your code lacks a style definition. For a graduated style you have to create a style object using styleGrad. The prop parameter in styleGrad specifies the property you want to visualize.
library("maptools")
library("sp")
library("leafletR")
SP <- readShapePoly(system.file("shapes/sids.shp",
package="maptools")[1],
proj4string=CRS("+proj=longlat +datum=WGS84
+no_defs +ellps=WGS84
+towgs84=0,0,0"))
SP4leaflet <- toGeoJSON(data=SP, dest=tempdir(), name="BIR79")
SPleaflet <- leaflet(data=SP4leaflet, dest=tempdir(),
title="Trying to plot BIR79",
base.map="osm", popup="*")
## missing style definition
brks <- seq(0, max(SP$BIR79), by=5000)
clrs <- colorRampPalette(c("blue","yellow", "red"))(7)
stl <- styleGrad(prop="BIR79", breaks=brks, style.val=clrs,
out=1, leg="BIR79")
## end style definition
SPleaflet <- leaflet(data=SP4leaflet, dest=tempdir(),
title="Trying to plot BIR79", base.map="osm",
style=stl, popup="*")
SPleaflet
Maybe something like this works. Note that I used leaflet not leafletR. There is a good intro about the package here: here
library(leaflet)
library(maptools)
library(sp)
library(classInt)
library(classInt)
SP <- readShapePoly(system.file("shapes/sids.shp",
package="maptools")[1],
proj4string=CRS("+proj=longlat +datum=WGS84
+no_defs +ellps=WGS84
+towgs84=0,0,0"))
spplot(SP, zcol="BIR79")
## 6 classes with fixed given breaks
nclass <- classIntervals(SP$BIR79, n=6)
## Color for each class
colcode = findColours(nclass, c("red", "blue"))
leaflet(SP) %>% addTiles() %>% addPolygons(data = SP, color = colcode)

Map raw data and mean data based on the shapefile

sI have the dataset (pts) like this:
x <- seq(-124.25,length=115,by=0.5)
y <- seq(26.25,length=46,by=0.5)
z = 1:5290
longlat <- expand.grid(x = x, y = y) # Create an X,Y grid
pts=data.frame(longlat,z)
names(pts) <- c( "x","y","data")
I knew that I can map the dataframe (pts) into a map by doing:
library(sp)
library(rgdal)
library(raster)
library(maps)
coordinates(pts)=~x+y
proj4string(pts)=CRS("+init=epsg:4326") # set it to long, lat
pts = spTransform(pts,CRS(" +init=epsg:4326 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0"))
pts <- as(pts, "SpatialPixelsDataFrame")
r = raster(pts)
projection(r) = CRS(" +init=epsg:4326 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0")
plot(r)
map("usa",add=T)
Now I would like to create a separate map which shows the means of pts across different regions. The shapefile I want to use is from ftp://ftp.epa.gov/wed/ecoregions/cec_na/NA_CEC_Eco_Level2.zip , however, this is a north america map. How can I create the map showing only US based on this north america map? Or is there another better way to do this? thanks so much.
I think that cutting out the non-US data based on the data in the shapefile alone would be hard, since the regions do not correspond to political boundaries - that could be done with rgeos though.
Assuming that "eco" is a SpatialPolygonsDataFrame read in by rgdal::readOGR or maptools::readShapeSpatial, see the available key data for indexing:
sapply(as.data.frame(eco), function(x) if(!is.numeric(x)) unique(x) else NULL)
If you just want to plot it, set up a map with only the US region to start with and then overplot.
library(maps)
map("usa", col = "transparent")
We see that the data is in Lambert Azimuthal Equal Area:
proj4string(eco)
[1] " +proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs"
So
require(rgdal)
eco.laea <- spTransform(eco, CRS("+proj=longlat +ellpse=WGS84"))
plot(eco.laea, add = TRUE)
If you want to plot in the original Lambert Azimuthal Equal Area you'll need to get the bounding box in that projection and start the plot based on that, I just used existing data to make an easy example. I'm pretty sure the data could also be cropped with rgeos against another boundary too, but depends what you actually want.

Resources