changing extent of SpatVector for better visualisation - r

library(geodata)
ct_shp <- geodata::gadm('USA', level = 0, path=".")
plot(ct_shp)
When I plot the USA, I get this.
Any raster I plot for US using this shapefile as a basemap becomes really small. The only solution I have is to crop out polygons greater than 100 degrees longitude so that I get a bigger map of US and I can plot any US specifc raster for more appealing maps. I wondered if there's anyone who faces such issue and how they have dealt with it.

In this case I would first simplify the geometries a bit (that speeds things up, but is otherwise not related to your question).
library(geodata)
usa <- geodata::gadm('USA', level = 0, path=".")
usa <- simplifyGeom(usa, 0.01)
You can select the western hemisphere (or any other area) like this
e <- ext(-180, -60, 11, 78)
p <- crop(usa, e)
Alternatively, you can use rotate to eastern hemisphere bit so that it connects to the western hemisphere. For that you need "terra" >= 1.6-21 (currently the development version, you can install it with install.packages('terra', repos='https://rspatial.r-universe.dev'))
r <- rotate(usa, long=0, split=T)
plot(r)
This is still not a great basemap for the USA. There is a lot of whitespace and Alaska is way too big for most purposes. I would either use an appropriate (conical) map projection, or cut, resize, and move Alaska and Hawaii, but that is quite involved.

Related

Shifting the longitude of an sf object

I have a map of countries (sf object) and I would like to shift the longitude of the eastern portion of Russia so that it is not isolated from the rest of Russia.
See Image
I found the backend code for st_shift_longitude https://github.com/r-spatial/sf/blob/master/R/shift_longitude.R, which shifts all coordinates by 180 degrees, so that the resulting map looks as follows:
link
How can I modify this block of code to shift the eastern portion of Russia only?
shift_lon <- function(x){
xcrs = st_crs(x)
g = (x + c(360, 90)) %% c(360) - c(0, 90)
st_wrap_dateline(st_set_crs(g - c(180, 0), xcrs)) + c(180, 0)
st_set_crs(g, xcrs)
}
st_geometry(countries) <- shift_lon(st_geometry(countries))
Alternative solutions are also welcome.
You will need to break down your world object into two parts - one containing Russia, and other for the rest of world.
Then apply the pacific view / sf::st_shift_longitude() on the Russia part, and merge it back with the "rest of world" dataset.
In this example I am using the world dataset from giscoR package. It is my favorite, but it is not the only one available; and it has a feature (or a bug, depending on circumstances) of applying a thin interruption at the antimeridean; this results in an artefact around Chukotka in my map. Getting rid of it is a separate issue, and I am not certain you will be facing it with your version of the world dataset (so it may be, and may not be, relevant problem).
Anyway, here is a possible code implementation:
library(sf)
world <- giscoR::gisco_get_countries() # or your own world dataset
rossiya <- subset(world, ISO3_CODE == "RUS")
# shift Russia to a more Pacific centric worldview
pacified_rossiya <- st_shift_longitude(rossiya)
rest_of_world <- subset(world, ISO3_CODE != "RUS")
# this is the important section: bind together the shifted and unshifted parts
world2 <- rbind(pacified_rossiya,
rest_of_world)
plot(st_geometry(world2))

Removing outlying islands from US map in shapefile with R

I downloaded level-0 US map (National border) in R(sf) format from https://gadm.org/download_country_v3.html. I plotted US border (level 0) as follows:
library(tidyverse)
us0 <- readRDS("<file.path>\\gadm36_USA_0_sf.rds")
ggplot() +
geom_sf(data = us0, size = 1, color = "steelblue", fill = NA)
Resultant image shown below
I would like to remove outlying islands A and B, and move Alaska from C to C'.
I tried but failed to extract longitude and latitude data from us0. I searched online but did not find adequate answers on how to do this in R. I would like to know how longitude and latitude data could be extracted from us0 with R so that I can freely delete A and B and remove C. Thank you.
using the raster package and the geom() function you can extract the raw coordinates from the RDS object, as well as which island/state the coordinate is part of and whether it is solid or a hole.
In your case:
geom(us0)
Then it's just a matter of finding out which vertices belong to which islands. A quick way of deleting B would be to delete everything with a positive x coordinate. You'll need to find out which objects correspond to Alaska if you're to move and scale it. The top of Hawaii is (i.i.r.c) lower down than the bottom of the Florida Keys so you can also get away with removing everything with a latitude less than 23.
Also, I suspect many Hawaiians would object to Hawaii being referred to as an outlying island....

Crop out all mapped area beyond region of 13 U.S. states

I've just started with mapping in R and I've managed to convert a lat, lon dataframe to a raster file and then plot state borders on top of that.
Now I need to get it ready to publish and would like to include only the shape of my 13-state region (and no great lakes).
library(tmap)
usa <- st_as_sf(maps::map("state", fill=TRUE, plot =FALSE))
map_us<- tm_shape(usa)+
tm_borders()
tm_shape(raster_file) +
tm_raster(style = "cont", palette = "viridis", midpoint = 0)+
map_us
I'm having a hard time finding something out there that would provide a polygon for multiple states and I have been through a lot of mapping packages. Sorry I can't include my raster data here.
To crop a raster file to {sf} vector shape you have in principle two options:
crop at data level; this involves raster::mask() with possibly raster::crop() later to reduce the extent of the raster (masked raster retains the original size)
retain the data, and overlay a white polygon with a hole over your plot
Cropping on data level is more "pure", but will leave you with ragged edges (a raster cell has to be square).
Overlaying a white polygon is not so pure, but might be preferable if your key aim is a slick presentation (and purity of essence be damned...)
You will find both of them discussed, together with examples and sample code, in this post on the RStudio community site.

Impossible Nas in wrld_simpl

When I create a raster of the world land based on wrld_simpl (or any other environmental layer coming from worldclim) always appear to be some "impossible" NAs on land. Why would that happen? I need a perfect mask of the world land to excerpt records that did not fall in the ocean. However, there are many records on land and still are considered NA.
My script goes like this:
require(raster)
require(maptools)
data(wrld_simpl)
x=read.csv("https://www.dropbox.com/s/ncvu64r2fxgfd4e/NAlocations.csv?dl=0")
r=raster(ncols=360,nrows=(180))
extent(r)=extent(wrld_simpl)
r=rasterize(wrld_simpl,r,wrld_simpl$AREA)
plot(r)
x=x[-which(is.na(extract(r,x$lon,x$lat))),]# This should eliminate all locations on land.
points(x$lon,x$lat, col="red", cex=.3)
How is that possible? And would it be a way to create a clean raster for the world land?
The direct read.csv from dropbox does not work for me.
If I do
z <- extract(r, x)
# NOT z <- extract(r, x[,1], x[,2]) !!!
i <- which(is.na(z))
points(x[i,])
I see a bunch of points in the water of the coast of Mozambique.

ggmap - merging two satellite ggmaps into 1 ggmap

I am trying to map data onto higher resolution Google satellite imagery. I could use a lower resolution image (e.g. zoom 13 and limit the scales - as suggested here - ggmap extended zoom or boundaries) however, the resultant image is not clear enough for my purpose. So basically I would like to be able to combine 2 14 zoom into 1 ggmap:
library(ggmap)
library(gridExtra)
g1 <- get_googlemap(center = c(-83.986927, 33.955656), maptype="satellite", zoom=14)
g2 <- get_googlemap(center = c(-83.938079, 33.955656), maptype="satellite", zoom=14)
gmap1 <- ggmap(g1)
gmap2 <- ggmap(g2)
grid.arrange(gmap1, gmap2, ncol =2)
but have 1 ggmap object that combined gmap1 and gmap2.
You can (and probably should) convert to raster objects. You should really use them independently from then on, like tiles, since their pixels don't seem to be on the same grid basis so mosaicing them might not be perfect. You can bodge this by adjusting the tolerance.
The objects from get_googlemap are matrices with colour values in hex ("#FF000" etc) and some attributes defining the extent. The following code converts that object to a three-band RGB raster, with the right extent and CRS:
library(raster)
ggmap2raster <- function(g){
rgb = col2rgb(g)
bands = apply(rgb, 1, function(band){
raster(t(matrix(band,ncol=ncol(g), nrow=nrow(g))))
})
s = stack(bands)
bb = attr(g, "bb")
extent(s) = extent(bb$ll.lon,bb$ur.lon, bb$ll.lat, bb$ur.lat)
crs(s) <- "+init=epsg:4326"
s
}
To merge a bunch of them, this code uses mosaic, but because the layers don't seem to line up quite right (possibly because the data are really in web mercator rather than WGS84) you need to up the tolerance and hope:
mergegg <- function(glist){
m = function(...){
mosaic(...,tolerance=0.5, fun=min)
}
do.call(m,
lapply(glist, function(g){
ggmap2raster(g)
})
)
}
> r = mergegg(list(g1, g2))
> plotRGB(r)
I suspect the tolerance problem may disappear if I convert the corner coords back to Web Mercator. But that's too much bother for a Friday morning. ggmap and its handling of coordinate systems is not something I want to get into right now. You could try binding the two g1 and g2 matrix objects together but you probably would have to do the reverse transform first and to be honest given the restrictions on using Google satellite images (you have read the license conditions?) I suspect its a bad thing.
To visualise raster objects, use the tmap package instead of ggmap.

Resources