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!
Related
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.
I have a map of landcover data in R and want to clip a circle of specific area, say 20km, and extract the resultant circular shapefile.
# read in the shape file, assign the CRS and plot it
area <- readShapePoly("Corrine Land Use ITM Projection - Copy.shp", proj4string = CRS("+init=epsg:2157"))
plot(area, xlim = c(560000,600000), ylim = c(530000,580000), axes=TRUE)
# create a dataframe of the location where the buffer should be made and plot it
locations<-data.frame(latitude=584503.3,longitude = 560164.5)
points(locations, bg='tomato2', pch=21, cex=3)
Do I need to change my points into a coordinate system first before I do this?
The shape file is the Corine Landcover 2012 - National http://gis.epa.ie/GetData/Download
Thanks
Your polygons
area <- shapefile("Corrine Land Use ITM Projection - Copy.shp")
You can create a circle (or multiple circles) like this:
library(dismo)
p <- polygons(circles(cbind(0,0), sqrt(20000 / pi), lonlat=FALSE, dissolve=FALSE))
crs(p) <- crs(area)
Intersect
int <- crop(area, p)
Write
shapefile(int, 'landcover_circle.shp')
#Manassa: I believe you will need to ensure the shapefile and raster are in the same projection before you clip, then you can use the crop function in the raster library. Please note, the output will be a clipped raster, not a shapefile as stated in your original question.
# Reproject shapefile to same projection as the raster
#shp = shapefile
#r = raster
library(rdgal)
shp.reproject <- spTransform(shp, crs(r))
#crop raster with polygon
library(raster)
r.crop <- crop(r, shp.reproject)
I am using {raster} to clip (or crop) a raster based on an irregular shapefile (the Amazon biome) but the output always has a rectangular extent. However, I need the output in the exact same geometry of the shapefile. Any tips? Cheers.
library(raster)
library(rgdal)
myshp <- readOGR("Amazon.shp", layer="Amazon")
e <- extent(myshp)
myraster <- raster("Temperature.tif")
myraster.crop <- crop(myraster, e, snap="out", filename="myoutput.tif")
One option is to use raster::mask()
library(maptools) ## For wrld_simpl
library(raster)
## Example SpatialPolygonsDataFrame
data(wrld_simpl)
SPDF <- subset(wrld_simpl, NAME=="Brazil")
## Example RasterLayer
r <- raster(nrow=1e3, ncol=1e3, crs=proj4string(SPDF))
r[] <- 1:length(r)
## crop and mask
r2 <- crop(r, extent(SPDF))
r3 <- mask(r2, SPDF)
## Check that it worked
plot(r3)
plot(SPDF, add=TRUE, lwd=2)
Package terra:: made it simpler, you can ::crop and mask in the same step.
# Load packages
library(maptools) # For geometry
library(terra) # Perform the crop and mask
###--- Preparing polygon and raster ---###
# Example SpatialPolygonsDataFrame
data(wrld_simpl)
polygon <- subset(wrld_simpl, NAME=="Luxembourg")
plot(polygon) # have a look
# Convert from SpatialPolygonsDataFrame to SpatVector (terra package format)
# And create a smaller polygon with buffer (negative to be "inside")
polygon_bf <- buffer(vect(polygon), width= -100000)
plot(polygon_bf, add= T) # have a look on both
# Create a SpatRaster from a file
f <- system.file("ex/elev.tif", package="terra")
r_lux <- rast(f)
plot(r_lux) # have a look on SpatRaster (terra package format)
# See the steps with plot
plot(polygon, add= T)
plot(polygon_bf, add= T)
Click to see intermediate steps (all files)
########################################################
### Crop and mask by any polygon ###
raster_cp <- crop(r_lux, polygon_bf, mask= T)
# Note: if mask= F, the crop will be by extent (box) ###
########################################################
### Check the results
plot(raster_cp)
plot(polygon_bf, lwd=1, add=T)
Click to see the final output
In addition, (with raster package) in case you want to perform with a simple geometry (i.g. box), the coordinates of the extent can be place directly:
e <- as(extent(c(xmin= -16, xmax= -7.25, ymin= 4, ymax= 12.75)), 'SpatialPolygons')
crs(e) <- "+proj=longlat +datum=WGS84 +no_defs"
r <- crop(my_raster, e)
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))
How can I plot a "raster" object behind a shapefile object? Both plot fine on their own but the points don't plot over the raster:
require(rgdal)
require(maptools)
require(raster)
myproj = "+proj=utm +zone=12 +north +ellps=WGS84 +units=m"
shp = readShapeSpatial(fn.shp, proj4string = CRS(myproj))
ras = raster(fn.tif)
plot(ras)
plot(shp, bg="transparent", add=TRUE)
Overplotting raster plots with points, lines, and polygons should work just fine, as the following example shows.
My best guess would be that the Spatial* objects you are attempting to plot on top of the raster fall outside of the region being plotted. Have you checked that both the raster and Spatial* objects are in the same CRS, and (assuming they are) that the bounding boxes overlap? (i.e. try bbox(shp) and bbox(ras), and compare the results).
library(rgdal)
library(raster)
# Create a raster
ras <- raster(ncols=36, nrows=18)
ras[] <- runif(ncell(ras))
# Create a SpatialPoints object
shpPts <- spsample(Spatial(bbox=bbox(ras)), 20, type="random")
# Create a SpatialPolygons object
p1 <- rbind(c(-10,0), c(140,60), c(160,0), c(140,-55), c(-10,0))
shpPolys <- SpatialPolygons( list(Polygons(list(Polygon(p1)), 1)))
# Plot them, one layer after another
plot(ras)
plot(shpPts, pch=16, col="red", add=TRUE)
plot(shpPolys, col="yellow", add=TRUE)