Plotting a shapefile on a raster layer in R - 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)

Related

Issues plotting spatial point data using tmap

I have created a class Large SpatialPointDataFrame from a csv file, and I am trying to plot the data points using tmap. When I plotted the SpatialPointDataFrame using plot(), everything looked fine. However, when I tried to plot it using tmap, it only shows one single point plus it is not where it should be, btw, the point that got shown is the last item in the data frame.
I'm thinking there might be something wrong with my projecton? CRS(Using SVY21 or EPSG:3414) properties of the SpatialPointDataFrame:
crs: +init=epsg:3414 +proj=tmerc +lat_0=1.366666666666667 +lon_0=103.8333333333333 +k=1 +x_0=28001.642 +y_0=38744.572 +ellps=WGS84 +units=m +no_defs
This is how I converted the dataframe to a spatialpointdataframe, where listing is the original dataframe read from a csv file.
coords <- listing[ , c("latitude", "longitude")]
crs <- CRS("+init=epsg:3414")
listing_sp <- SpatialPointsDataFrame(coords = coords, listing, proj4string = crs)
Any suggestions on how I should debug?
In your code, where you have crs <- CRS("+init=epsg:3414"), you are assigning a projection but your source data has not yet been transformed to that projection. If your source data is in lat/lon it's meant to be used with the WGS84 projection (epsg code 4326).
Once you create your spatialPointDataFrame using the projection matching your coordinates, you simply have to reproject using spTransform. To reproject to SVY21, you still need to transform. Can't test without some reproducible data but it should look like this.
coords <- listing[ , c("latitude", "longitude")]
crs <- CRS("+init=epsg:4326")
listing_sp <- SpatialPointsDataFrame(coords = coords, listing, proj4string = crs)
listing_sp_svy21 <- spTransform(listing_sp, CRS("+init=epsg:3414"))

How to project Hydrologic Rainfall Analysis Data (MPE/AHPS) raster to a usable format?

Apparently NOAA and the NWS use a non-traditional projection for some of their rainfall data and don't offer a lot of help in terms of projecting it to a traditional format for other users. I've had a bit of success in getting the raster to overlay for part of the United States but it still isn't quite right.
I'm hoping someone can help me decipher what I am missing and correct the projection of this data.
You can find more information of this data here: https://polyploid.net/blog/?p=216
https://water.weather.gov/precip/download.php
library(tidyverse)
library(raster)
library(rgdal)
library(sp)
setwd("C:/Users/MPE_Data/")
file_list <- list.files("201809")
grib0<-raster::brick("201809//ST4_2018091307_24h.nc", varname="APCP_SFC")[[1]]
grib0#crs
crs(grib0) <- "+proj=longlat +a=6371200 +b=6371200 +no_defs"
crs(grib0) <- "+proj=stere +lat_0=90 +lat_ts=60 +lon_0=-105 +x_0=0 +y_0=0 +a=6371200 +b=6371200 +units=m +no_defs"
us_shp <- rgdal::readOGR("C:/Users/cb_2017_us_state_500k/US_clipped.shp")
shp <- rgdal::readOGR("C:/Users/nc_sc_counties_wgs1984.shp")
wgs<-"+proj=longlat +datum=WGS84 +ellps=WGS84 +no_defs"
wgsraster <- projectRaster(grib0, crs=wgs)
plot(wgsraster)
shp <- spTransform(shp, CRS(wgs))
us_shp <- spTransform(us_shp, CRS(wgs))
plot(shp,add=TRUE)
plot(us_shp,add=TRUE)
I couldn't find your exact map but here is an example using recent precipitation data. You don't need to assign a CRS as the netCDF file already has a CRS associated with it, you can simply projectRaster. Also the NOAA website has the option to download to geoTIFF which I would recommend if you are more comfortable with that.
require(raster)
require(ncdf4)
require(maptools)
data(wrld_simpl)
us_shp=wrld_simpl[which(wrld_simpl$NAME=="United States"),]
rs=raster::brick("./nws_precip_1day_20200509_netcdf/nws_precip_1day_20200509_conus.nc",varname="observation")[[1]]
rs#crs ##note already has a crs associated with it
+proj=stere +lat_0=90 +lat_ts=60 +lon_0=-105 +x_0=0 +y_0=0 +a=6371200
+b=6371200 +units=m +no_defs
##assign the pixels with -10000 to NA.
NAvalue(rs) = -10000
##reproject to longlat WGS84
rs=projectRaster(rs,crs=crs(us_shp))
plot(rs,col=rainbow(100))
lines(us_shp)
##note the data extends outside the bounds of country
##use mask to remove data that is not over the land area
rs=mask(rs,us_shp)
plot(rs,col=rainbow(100)
lines(us_shp)
Note that the maximum value of rs changed from 7.8 to 7.0 due to the bilinear interpolation method used in projectRaster. You need to consider whether you require bilinear or nearest neighbour interpolation and if you need to be specific about the output raster resolution and extent I would suggest supplying a model raster for the to argument.
Edited to incorporate #Robert Hijmans' suggestion.

Set coordinate reference system to a polygon created in R

I am trying to create a zoom-in square(polygon) in a map that is plot using ggplot2::geom_sf()
Therefore, I need the polygon to be a simple feature so I can plot the square and the map together.
I could create the polygon using the following code.
zoom_square_1<- rbind(c(-10.821079,-68.403542),
c(-10.821079,-68.367060),
c(-10.862918,-68.367060),
c(-10.862918,-68.403542),
c(-10.821079,-68.403542)) # add the first point again to it wrap up.
zoom_square_1_pol <- st_polygon(list(zoom_square_1))
plot(zoom_square_1_pol) # it returns the polygon.
However, when I tried to assign a Coordinate reference system (CRS) to it, it does not work. These are the codes I have tried so far.
sp::proj4string(zoom_square_1_pol) <- CRS("+proj=longlat +datum=WGS84 +no_defs")
zoom_square_1_pol_ex1 <- st_as_sf(x = zoom_square_1_pol[[1]],
crs = "+proj=longlat +datum=WGS84 +no_defs")
zoom_square_1_pol_ex2 <- st_transform(x = zoom_square_1_pol,
crs = "+proj=longlat +datum=WGS84 +no_defs")
Any help is welcomed.
After Chris comment, I could actually plot the polygons using ggplot2::geom_sf() and realized that my lat and long coordenates were in the wrong position since the begging. So, this the is final version of the code:
zoom_square_1<- rbind(c(-68.403542,-10.821079),
c(-68.367060,-10.821079),
c(-68.367060,-10.862918),
c(-68.403542,-10.862918),
c(-68.403542,-10.821079)) #add the first point again to it wrap up.
zoom_square_1_pol <- st_polygon(list(zoom_square_1))
zoom_square_1_pol_CRS<- st_sfc(x = zoom_square_1_pol,
crs = "+proj=longlat +datum=WGS84 +no_defs")
I was able to set the crs by feeding the square as a list to st_as_sfc:
res <- st_as_sfc(list(zoom_square_1_pol),
crs = "+proj=longlat +datum=WGS84 +no_defs")

R Levelplot overlaying two SpatialPolygonsDataFrame on a RasterLayer projection

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.

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