SpatialLines instead of segments (spplot) - r

I'd like to use spplot + sp.lines (lattice) instead of plot + segments. Do you know a simple way to realise this, e.g. R: Calculating the shortest distance between two point layers
library(dismo)
require(rgdal)
require(FNN)
laurus <- gbif("Laurus", "nobilis")
locs <- subset(laurus, !is.na(lat) & !is.na(lon),
select = c("country", "lat", "lon"))
locs.uk <- subset(locs, locs$country=="United Kingdom")
locs.ire <- subset(locs, locs$country=="Ireland")
uk_coord <- SpatialPoints(locs.uk[,c("lon","lat")])
ire_coord <- SpatialPoints(locs.ire[,c("lon","lat")])
crs.geo<-CRS("+proj=longlat +ellps=WGS84 +datum=WGS84")
proj4string(uk_coord) <- crs.geo
proj4string(ire_coord) <- crs.geo
uk_coord <- spTransform(uk_coord, CRS("+init=epsg:27700"))
ire_coord <- spTransform(ire_coord, CRS("+init=epsg:27700"))
g = get.knnx(coordinates(uk_coord), coordinates(ire_coord),k=1)
to visualise this
plot(uk_coord, col=2, xlim=c(-1e5,6e5))
plot(ire_coord, add=TRUE)
segments(coordinates(ire_coord)[,1],
coordinates(ire_coord)[,2],
coordinates(uk_coord[g$nn.index[,1]])[,1],
coordinates(uk_coord[g$nn.index[,1]])[,2])
can probably converted to something like
ire <- list("sp.points", ire_coord)
spplot(uk_coord, sp.layout=list(ire))
but is there a easy way to convert segments to SpatialLines i.e. list("sp.lines", Lines(...))

Try panel.segments() from the lattice-package:
library("lattice")
spplot(rbind(uk_coord, ire_coord), auto.key=FALSE,
panel=function(...) {
panel.xyplot(...)
panel.segments(coordinates(ire_coord)[,1],
coordinates(ire_coord)[,2],
coordinates(uk_coord[g$nn.index[,1]])[,1],
coordinates(uk_coord[g$nn.index[,1]])[,2])
})

Understanding panel functions is more powerful than relying on sp.layout in spplot -- and so is using lattice or grid functions directly. The solution with sp.layout could look like this:
spplot(uk_coord, auto.key=FALSE, col.regions = 'black',
sp.layout = list(ire,
list("panel.segments",
coordinates(ire_coord)[,1],
coordinates(ire_coord)[,2],
coordinates(uk_coord[g$nn.index[,1]])[,1],
coordinates(uk_coord[g$nn.index[,1]])[,2])),
xlim = c(-140000,700000))
note that it is not restricted to the sp.lines etc functions; in upcoming sp 1.1-0, quotes around function names can also be omitted.
spplot tries to plot attributes of features in color by default, which is not meaningful here, so what you basically want is an xyplot with controlled aspect ratio (asp="iso").

Related

From rastermap package to ggplot2

My problem: I want to draw a map obtained via rastermap package with ggplot2.
Searching for alternatives to ggmap package I found the rastermap package which provides an easy way to obtain maps from external sources. The readme provides a very simple example:
# install.packages("devtools")
devtools::install_github("hadley/rastermap")
houston <- fetch_region(c(-95.80204, -94.92313), c(29.38048, 30.14344),
stamen("terrain"))
houston
plot(houston)
The problem comes whether I try to plot using ggplot. So far I've tried several ways but none of them seems to work. Is it possible? Any idea?
rastermap generates a matrix of colours in hexadecimal strings (#RRGGBB format). It may be simplest to convert this to a more common form for spatial data, a multiband raster brick, with separate layers for the red, green and blue.
We can write a short helper function to convert hexadecimal strings into the separate integer values (i.e. this is the reverse of the rgb() function):
un_rgb = function (x) {
x = unlist(str_split(x, ''))
r = paste0(x[2], x[3])
g = paste0(x[4], x[5])
b = paste0(x[6], x[7])
strtoi(c(r,g,b), 16)
}
Using this function we convert the rastermap matrix into a three band raster brick:
library(raster)
m = as.matrix(houston)
l=lapply(m[], un_rgb)
r=g=b=matrix(, dim(m)[1], dim(m)[2])
r[] = sapply(l, function(i) i[1])
g[] = sapply(l, function(i) i[2])
b[] = sapply(l, function(i) i[3])
rgb.brick = brick(raster(r), raster(g), raster(b))
And set the extent of the new raster to that of the original rastermap
extent(rgb.brick) = extent(matrix(unlist(attributes(houston)$bb), nrow=2))
Now that we have a more usual form of raster object, we can do various things with it. For example, we can plot it in ggplot using library(RStoolbox):
ggRGB(rgb.brick, r=1, g=2, b=3)
Or we can save it as an image to use as an annotation background in ggplot:
png('test.png', dim(rgb.brick)[2], dim(rgb.brick)[1])
plotRGB(rgb.brick, 1, 2, 3)
dev.off()
img <- png::readPNG("test.png")
gr <- grid::rasterGrob(img, interpolate=TRUE)
ggplot() + annotation_custom(gr, -Inf, Inf, -Inf, Inf)
Why would you want an alternative? You can get a stamen map from ggmap:
library(ggmap)
ggmap(get_stamenmap(c(-95.80204, 29.38048, -94.92313, 30.14344))) +
# some points to plot
geom_point(aes(x = seq(-95.5, -95.2, 0.1), y = seq(29.7, 30, 0.1)), color = "red")

Draw boundaries using groups and order for each region gg_map Rgooglemaps

I'm trying to plot custom boundaries (dma's) into a google map.
library(ggmap)
library(ggplot2)
US <- get_map(location = c(-95.7129,37.0902),zoom = 3)
US_map <- ggmap(US)
then using the following CSV file with the coordinates groups and order
https://www.dropbox.com/s/3xv192k5401np4r/DMAs%20coordinates%20sample.csv?dl=0
Then I can plot the coordinates using dots:
smpl <- read.csv('DMAs coordinates sample.csv')
US_map + geom_point(data=smpl,aes(x=Longitude, y=Latitude),size=0.01)
But I would like to plot lines connected by these dots using the path from point_order and group each set of lines using dma_boundary.UniqueID I'm sure there's a way to do this. but I cannot find the right way.
I found a way to do this,
Using geom_path for each group represented by dma_boundaty.UniqueID
As the data is already sorted by sub_polygon_id and point_order we use geom_path to use the order set in data. Then,
library(ggplot2)
library(data.table)
library(ggmap)
dma_boundaty <- data.table(read.csv('.../path')
US <- get_map(location = c(-95.7129,37.0902),zoom = 3)
US_map <- ggmap(US)
dma_map <- US_map + lapply(0:205,function(i) {
geom_path(data=dma_boundary[dma_boundary.UniqueID == i,],aes(x=Longitude, y=Latitude))})

Put the name of the district on the plot

I am trying to make a plot of the intensity map of Ukraine's regions and intensity depends on the 'value'. Here is my code:
library(sp)
con <- url("http://biogeo.ucdavis.edu/data/gadm2/R/UKR_adm1.RData")
print(load(con))
close(con)
name<-VARNAME_1
gadm$VARNAME_1
value<-c(1:27)
gadm$VARNAME_1<-as.factor(value)
col<- colorRampPalette(c('white', 'black'))(256)
spplot(gadm, "VARNAME_1", main="Ukraine", scales = list(draw = TRUE), col.regions=col)
My question is: Is it possible to put on the plot the names of the regions (I have it as a character vector name in my code to the appropriate place on the map. Or maybe another suggestion to make a map more clear and understandable which region has corresponding value.
Thank you!
one possibility is to do it with colors :
colors=rainbow(length(gadm$NAME_1))
plot(gadm,col=colors)
legend("topleft",legend=gadm$NAME_1,fill=colors,cex=1.3,bty="n" )
or you add names with text :
colors=rainbow(length(gadm$NAME_1))
plot(gadm,col=colors)
text(coordinates(gadm), labels = gadm$NAME_1)
This solution uses plot instead of spplot so we can add labels with text. If you still want to use spplot, check
x11()
col = cm.colors(length(gadm$PID))
plot(gadm, , col=col[rev(gadm$VARNAME_1)])
text(coordinates(gadm), labels = gadm$NAME_1, cex=0.4)
Or if you still want to use spplot, be prepared to do a bit extra. Here's a modification of this answer
sp.label <- function(x, label) {
list("sp.text", coordinates(x), label)
}
NAME.sp.label <- function(x) {
sp.label(x, x$NAME_1)
}
draw.sp.label <- function(x) {
do.call("list", NAME.sp.label(x))
}
spplot(gadm, 'VARNAME_1', sp.layout = draw.sp.label(gadm))

Overlap image plot on a Google Map background in R

I'm trying to add this plot of a function defined on Veneto (italian region)
obtained by an image and contour:
image(X,Y,evalmati,col=heat.colors(100), xlab="", ylab="", asp=1,zlim=zlimits,main=title)
contour(X,Y,evalmati,add=T)
(here you can find objects: https://dl.dropboxusercontent.com/u/47720440/bounty.RData)
on a Google Map background.
I tried two ways:
PACKAGE RGoogleMaps
I downloaded the map mbackground
MapVeneto<-GetMap.bbox(lonR=c(10.53,13.18),latR=c(44.7,46.76),size = c(640,640),MINIMUMSIZE=TRUE)
PlotOnStaticMap(MapVeneto)
but i don't know the commands useful to add the plot defined by image and contour to the map
PACKAGE loa
I tried this way:
lat.loa<-NULL
lon.loa<-NULL
z.loa<-NULL
nx=dim(evalmati)[1]
ny=dim(evalmati)[2]
for (i in 1:nx)
{
for (j in 1:ny)
{
if(!is.na(evalmati[i,j]))
{
lon.loa<-c(lon.loa,X[i])
lat.loa<-c(lat.loa,Y[j])
z.loa<-c(z.loa,evalmati[i,j])
}
}
}
GoogleMap(z.loa ~ lat.loa*lon.loa,col.regions=c("red","yellow"),labels=TRUE,contour=TRUE,alpha.regions=list(alpha=.5, alpha=.5),panel=panel.contourplot)
but the plot wasn't like the first one:
in the legend of this plot I have 7 colors, and the plot use only these values. image plot is more accurate.
How can I add image plot to GoogleMaps background?
If the use of a GoogleMap map is not mandatory (e.g. if you only need to visualize the coastline + some depth/altitude information on the map), you could use the package marmap to do what you want. Please note that you will need to install the latest development version of marmap available on github to use readGEBCO.bathy() since the format of the files generated when downloading GEBCO files has been altered recently. The data from the NOAA servers is fine but not very accurate in your region of interest (only one minute resolution vs half a minute for GEBCO). Here is the data from GEBCO I used to produce the map : GEBCO file
library(marmap)
# Get hypsometric and bathymetric data from either NOAA or GEBCO servers
# bath <- getNOAA.bathy(lon1=10, lon2=14, lat1=44, lat2=47, res=1, keep=TRUE)
bath <- readGEBCO.bathy("GEBCO_2014_2D_10.0_44.0_14.0_47.0.nc")
# Create color palettes for sea and land
blues <- c("lightsteelblue4", "lightsteelblue3", "lightsteelblue2", "lightsteelblue1")
greys <- c(grey(0.6), grey(0.93), grey(0.99))
# Plot the hypsometric/bathymetric map
plot(bath, land=T, im=T, lwd=.03, bpal = list(c(0, max(bath), greys), c(min(bath), 0, blues)))
plot(bath, n=1, add=T, lwd=.5) # Add coastline
# Transform your data into a bathy object
rownames(evalmati) <- X
colnames(evalmati) <- Y
class(evalmati) <- "bathy"
# Overlay evalmati on the map
plot(evalmati, land=T, im=T, lwd=.1, bpal=col2alpha(heat.colors(100),.7), add=T, drawlabels=TRUE) # use deep= shallow= step= to adjust contour lines
plot(outline.buffer(evalmati),add=TRUE, n=1) # Outline of the data
# Add cities locations and names
library(maps)
map.cities(country="Italy", label=T, minpop=50000)
Since your evalmati data is now a bathy object, you can adjust its appearance on the map like you would for the map background (adjust the number and width of contour lines, adjust the color gradient, etc). plot.bath() uses both image() and contour() so you should be able to get the same results as when you plot with image(). Please take a look at the help for plot.bathy() and the package vignettes for more examples.
I am not realy inside the subject, but Lovelace, R. "Introduction to visualising spatial data in R" might help you
https://github.com/Robinlovelace/Creating-maps-in-R/raw/master/intro-spatial-rl.pdf From section "Adding base maps to ggplot2 with ggmap" with small changes and data from https://github.com/Robinlovelace/Creating-maps-in-R/archive/master.zip
library(dplyr)
library(ggmap)
library(rgdal)
lnd_sport_wgs84 <- readOGR(dsn = "./Creating-maps-in-R-master/data",
layer = "london_sport") %>%
spTransform(CRS("+init=epsg:4326"))
lnd_wgs84_f <- lnd_sport_wgs84 %>%
fortify(region = "ons_label") %>%
left_join(lnd_sport_wgs84#data,
by = c("id" = "ons_label"))
ggmap(get_map(location = bbox(lnd_sport_wgs84) )) +
geom_polygon(data = lnd_wgs84_f,
aes(x = long, y = lat, group = group, fill = Partic_Per),
alpha = 0.5)

How to plot additional raster with spplot?

I want to plot SpatialPolygonsDataFrame as a semi-transparent main object (with legend on the right), but I want to plot yet additional raster (hillshade) as a background - just to make nicer map. I would need something like:
spplot(polygons, sp.layout = list(list("raster", myRaster)))
but looking at ?spplot, it doesn't seem to be possible to specify the raster in sp.layout. I can't specify the raster as the main object, because the main object are the polygons dataFrame, whose value scale I want to plot in the legend on the right side.
How is it possible to plot an additional raster in spplot?
Here's one way to do it. There's probably a neater way to achieve it without plotting the polygon object twice, though...
library(sp)
library(rasterVis)
r <- raster(nrow=18, ncol=36)
r[] <- runif(ncell(r)) * 10
r[r > 8] <- NA
pol <- rasterToPolygons(r, function(x) x > 6)
spplot(pol) + levelplot(r) + spplot(pol)
Or alternatively:
library(latticeExtra)
spplot(pol) + spplot(r) + spplot(pol)
EDIT
As per the comment by #OscarPerpiñán, a better way to do this is:
spplot(pol) + as.layer(spplot(r), under = TRUE)

Resources