Plot global projected raster in R - r

I'm trying to plot a global (lon:-180- 180; lat -90- 90) raster in Equal Earth projection (doesn't matter - could be Winkel Tripel or Robinson) but the boundaries duplicate on both sides (see figure). How can I avoid this?
This SO question and this thread give an answer that only works for plotting in Mollweide, but no other projection.
Here's a reproducible example.
library(maptools)
library(raster)
data("wrld_simpl")
r <- raster(ncol=180, nrow=90)
r <- rasterize(wrld_simpl, r, field="UN")
world_ext = projectExtent(wrld_simpl, crs = '+proj=longlat +datum=WGS84 +no_defs ')
r <- crop(x = r, y = world_ext, snap= 'in')
r <- projectRaster(r, crs = crs("+proj=wintri"), over = T)
plot(r)
Many thanks!

You can use the mask=TRUE argument in terra::project for this
library(maptools)
library(terra)
data("wrld_simpl")
w <- vect(wrld_simpl)
r <- rast(ncol=180, nrow=90)
r <- rasterize(w, r, field="UN")
x <- project(r, "+proj=wintri", mask=TRUE)

Related

Raster output from rasterized sf points does not align with points

I am trying to rasterize some points and am getting a mismatch between the points and the rasters despite the crs being the same. If I convert the raster to polygons it lines up perfectly with the sf points data, but I can't figure out why the raster doesn't.
library(spData)
library(sf)
library(raster)
library(mapview)
## import some data
cycle_hire_osm = spData::cycle_hire_osm
## project to metres
cycle_hire_osm_projected = st_transform(cycle_hire_osm, crs = 27700)
## create raster template to rasterize to
raster_template <- raster(extent(cycle_hire_osm_projected), nrows = 10, ncols = 10, crs = 27700)
## rasterize the points
ch_raster1 = rasterize(cycle_hire_osm_projected, raster_template, field = 'capacity',
fun = sum, crs = 27700)
## convert raster to polygons
ch_poly <- rasterToPolygons(ch_raster1)
If these are plotted there are raster cells that have a value but have no points in.
## plot on a map
mapview(ch_poly)+cycle_hire_osm_projected+ch_raster1
Additional example based on reply to show the output as base, mapview and leaflet (note: I had to install the development versions of mapview and leaflet in order to plot SpatRasts)
library(spData)
library(sf)
library(terra)
library(dplyr)
# remove NAs so they are not considered
dat <- spData::cycle_hire_osm %>% filter(!is.na(capacity))
v <- vect(dat)
r <- rast(v, nrows=10, ncols=10)
chr <- rasterize(v, r, field="capacity", fun=sum, na.rm=TRUE)
## base plot
plot(chr)
points(v, cex=.5)
points(v[is.na(v$capacity)], cex=.5, col="red")
## mapview
library(mapview)
mapview(v)+chr
##leaflet
library(leaflet)
leaflet() |>
addProviderTiles(providers$CartoDB.Positron) |>
addCircles(data = v) |>
addRasterImage(chr)
All three plots are the same raster but the raster appears to have a different number of cells with values in each plot?
Adding example with project = FALSE as explain by #RobertHijmans
leaflet() |>
addProviderTiles(providers$CartoDB.Positron) |>
addCircles(data = v) |>
addRasterImage(chr, project = FALSE)
I do not see that issue with "raster" nor with its replacement, "terra"
when using base-plot
library(spData)
library(terra)
# using a SpatVector for easier plotting; results are the same
v <- vect(spData::cycle_hire_osm)
v <- project(v, "epsg:27700")
r <- rast(v, nrows=10, ncols=10)
chr <- rasterize(v, r, field="capacity", fun=sum, na.rm=TRUE)
plot(chr)
points(v, cex=.5)
points(v[is.na(v$capacity)], cex=.5, col="red")
But note that there are some cells with values of zero where all values of v$capacity are NA. That is because
sum(NA, na.rm=TRUE)
#[1] 0
To avoid that from happening you could do
vv <- v[!is.na(v$capacity)]
chr <- rasterize(vv, r, field="capacity", fun=sum, na.rm=TRUE)
The reason you see differences when using mapview/leaflet is that these use transform your data to the crs that they use. To avoid that use the
Pseudo-Mercator (EPSG:3857) crs, and, in leaflet, use project=FALSE when adding the raster data.
addRasterImage(chr, project=FALSE)

select points over land area in R

I have a point vector for the entire globe at 0.25 degree resolution.
library(terra)
library(rnaturalearth)
# create point data
ref_grid <- terra::ext(-180, 180, -90, 90)
ref_grid <- terra::rast(ref_grid)
res(ref_grid)<- 0.25
values(ref_grid)<-1 #dummy values
projections <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
crs(ref_grid) <- projections
pts <- terra::as.points(ref_grid, values=TRUE, na.rm=TRUE)
# download world shapefile
world_shp <- rnaturalearth::ne_countries()
world_shp <- terra::vect(world_shp)
world_shp <- terra::project(world_shp, projections)
I want to extract those points that fall within a landmass i.e. remove all those points that are in the ocean. So I did this:
e <- terra::extract(world_shp, pts)
But it's been two hours now and this is still running. Is there any faster way to do this?
You should not transform raster data to vector data if you want efficiency. In this case, you can do the following in a second or so:
library(terra)
library(rnaturalearth)
ref_grid <- terra::rast(res=0.25)
world_shp <- rnaturalearth::ne_countries(returnclass="sf") |> vect()
ref_grid <- rasterize(world_shp, ref_grid)
p <- as.points(ref_grid)
(but perhaps, depending on what you do next, the last step should also be avoided)

Spatial polygons with messed up shape

I am new to spatial data. My goal is to get the gpx files from openstreetmap and plot polygons of Hungary's boundaries. I could successfully plot the boundaries under Járások but there are some boundaries under Kistérségek which are messed up, containing loops between points.
Image
Reproducable example for a specific boundary
library(XML)
library(magrittr)
library(sp)
parsed <- xmlParse("http://osmrm.openstreetmap.de/gpx.jsp?relation=1368104") %>% xmlToList()
coord <- do.call(rbind, parsed$rte)
name <- coord[1, 1]
coord <- coord[-(1:2), ]
coord <- apply(coord, 2, as.numeric)
poly <- Polygons(list(Polygon(coord)), name)
sp <- SpatialPolygons(list(poly), proj4string = CRS("+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"))
plot(sp)
Result
Is the error because I missed something, or is it simply an issue with openstreetmap data? Any help is appreciated.

Clipping raster using shapefile in R, but keeping the geometry of the shapefile

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)

Gadm map with points layer in R

I have already asked about plotting points dependent on region, but now my question is about overlaying points given by coordinations over gadm map. I want to show different meteostations, using data based on this site or here is data used in code I've tried using such code:
require(ggplot2)
library(maptools)
library(rgdal)
library(RColorBrewer)
library(gpclib)
library(rgeos)
library(PBSmapping)
gpclibPermit()
rus<-load("C://RUS_adm1.RData")
proj4.str <- CRS("+init=epsg:3413 +lon_0=105")
gadm.prj <- spTransform(gadm, proj4.str)
rus<-gadm.prj
met <- read.csv2('C:\\meteo.txt')
cds <- data.frame(
Longitude=met$Long,
Latitude=met$Lat)
k<-as.matrix(cds)
popSP <- SpatialPointsDataFrame(coords=k,met["Elevation"], proj4string=proj4.str)
spplot(popSP, sp.layout=list('sp.polygons', gadm.prj))
, following advice from already mentioneed question, but it ends up with plotting points w/o gadm layer , I guess it's because of non-mentioning regions
Sorry, if question is dumb, but I will be grateful for any help
Here is the answer. Thanks to flowla
Edited code a little bit, I could plot different plot according to elevation.
library(rgdal)
library(raster)
rus <- load("C://RUS_adm1.RData")
popSP <- met <- read.csv2("C://meteo.txt")
for (i in c(3, 4))
popSP[, i] <- popSP[, i] / 1000
coordinates(popSP) <- ~ Long + Lat
projection(popSP) <- projection(gadm)
# Reprojection to EPSG:3413 (see http://www.spatialreference.org/ref/epsg/3413/)
proj4.str <- CRS("+proj=stere +lat_0=90 +lat_ts=70 +lon_0=105 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs")
gadm.prj <- spTransform(gadm, proj4.str)
popSP.prj <- spTransform(popSP, proj4.str)
col_no <- as.factor(as.numeric(cut(popSP.prj$Elevation,
c(0,2500,5000,10000,15000,20000,100000))))
levels(col_no) <- c("<2500", "2500-5000","5000-10000", "10000-15000","15000-20000",">20000" )
color = rainbow(6)
popSP.prj$col_no<-col_no
spplot(popSP.prj, "col_no", sp.layout=list('sp.polygons',cols="ID_0", gadm.prj), col.regions=color, main="Meteostations in Russia", key.space="right")

Resources