Dealing with raster data in ggplot - r

I have a vector spatial data for the boundary of a county and topographical data for the same county in raster format.
I need to create a map with ggplot so that it only shows those data in raster format that are within the county boundaries (which in turn are in a vector spatial file).
In other words, I need to remove raster data that is outside the county outline. Is it possible to do this with ggplot?
Reproducible example:
# load packages
library(elevatr)
library(terra)
library(geobr)
# get the municipality shapefile (vectorized spatial data)
municipality_shape <- read_municipality(code_muni = 3305802)
plot(municipality_shape$geom)
# get the raster topographical data
prj_dd <- "EPSG:4674"
t <- elevatr::get_elev_raster(locations = municipality_shape,
z = 10,
prj = prj_dd)
obj_raster <- rast(t)
plot(obj_raster)
# create the ggplot map
df_tere_topo <- obj_raster %>%
as.data.frame(xy = TRUE) %>%
rename(altitude = file40ac737835de)
ggplot()+
geom_raster(data = df_tere_topo, aes(x = x, y = y, fill = `altitude`))+
geom_sf(municipality_shape, mapping = aes(), color = 'red', fill = NA)

Edited
See the comments, use terra::crop() and terra::mask() instead:
# load packages
library(elevatr)
library(terra)
library(geobr)
library(dplyr)
library(ggplot2)
# Use tidyterra
library(tidyterra)
# get the municipality shapefile (vectorized spatial data)
municipality_shape <- read_municipality(code_muni = 3305802)
# get the raster topographical data
prj_dd <- "EPSG:4674"
t <- elevatr::get_elev_raster(
locations = municipality_shape,
z = 10,
prj = prj_dd
)
obj_raster <- rast(t)
# Crop + Mask
obj_raster_mask <- crop(obj_raster, vect(municipality_shape)) %>%
mask(vect(municipality_shape))
# create the ggplot map
# using tidyterra
ggplot() +
geom_spatraster(data = obj_raster_mask) +
geom_sf(municipality_shape, mapping = aes(), color = "white", fill = NA) +
# Not plotting NAs of the raster
scale_fill_continuous(na.value = NA) +
labs(fill="altitude")
Original answer
I think the most efficient way is to crop your SpatRaster to the extent of your vector data. With this approach the plotting is more efficient since you are not using data that you don't wnat to plot.
Another option is to set limits in coord_sf().
On this reprex I am using the package tidyterra as well, that has some functions to work with ggplot2 + terra (I am the developer of tidyterra):
# load packages
library(elevatr)
library(terra)
library(geobr)
library(dplyr)
library(ggplot2)
# Use tidyterra
library(tidyterra)
# get the municipality shapefile (vectorized spatial data)
municipality_shape <- read_municipality(code_muni = 3305802)
# get the raster topographical data
prj_dd <- "EPSG:4674"
t <- elevatr::get_elev_raster(
locations = municipality_shape,
z = 10,
prj = prj_dd
)
obj_raster <- rast(t)
# Option1: Crop first
obj_raster_crop <- crop(obj_raster, vect(municipality_shape))
# create the ggplot map
# using tidyterra
ggplot() +
geom_spatraster(data = obj_raster_crop) +
geom_sf(municipality_shape, mapping = aes(), color = "white", fill = NA) +
coord_sf(expand = FALSE) +
labs(fill="altitude")
# Option 2: Use limits and no crop
lims <- sf::st_bbox(municipality_shape)
ggplot() +
geom_spatraster(
data = obj_raster,
# Avoid resampling
maxcell = ncell(obj_raster)
) +
geom_sf(municipality_shape, mapping = aes(), color = "white", fill = NA) +
coord_sf(
expand = FALSE,
xlim = lims[c(1, 3)],
ylim = lims[c(2, 4)]
) +
labs(fill="altitude")

Related

Create random points based in distance and boundary conditions

In my example, I have:
# Packages
library(sf)
library(ggplot2)
# Create some points
set.seed(1)
df <- data.frame(
gr = c(rep("a",5),rep("b",5)),
x = rnorm(10),
y = rnorm(10)
)
df <- st_as_sf(df,coords = c("x","y"),remove = F, crs = 4326)
df.laea = st_transform(
df,
crs = "+proj=laea +x_0=4600000 +y_0=4600000 +lon_0=0.13 +lat_0=0.24 +datum=WGS84 +units=m"
)
# Create a countour of the area
ch <- st_convex_hull(st_union(df.laea))
ggplot() +
geom_sf(data = ch, fill = "white", color = "black") +
geom_sf(data = df.laea,color = "black")
Now, I'd like to create 10 random points but the conditions are that this points must be inside the ch boundaries and a minimum distance of 10 meters of each df.laea points that exist inside this ch area.
Please, any help with it?
I think the only tricky thing here is that a simple st_difference() of your polygon and the buffered points will return ten polygons, each with one of the points removed. Thus you have to either use a for loop or reduce() to remove one buffered point after the other from the polygon. To use reduce() you have to transform the vector to a proper list of sf instead of an sfc vector. This is what I did below.
# Packages
library(sf)
library(ggplot2)
library(purrr)
ch_minus <- df.laea$geometry |>
st_buffer(10000) |>
{\(vec) map(seq_along(vec), \(x) vec[x])}() |> # Transform buffered points to reducible list
reduce(.init = ch, st_difference)
sampled_points <- st_sample(ch_minus, 10)
ch_minus |>
ggplot() +
geom_sf() +
geom_sf(data = sampled_points)
You can buffer the points by the distance you'd like, then intersect those polygons with the ch polygon. From there, use st_sample and the associated arguments to get the points you want.
Example code:
## buffer df.laea 10m
laea_buff <- st_buffer(df.laea, dist = 10000) #changed dist to 10km to make it noticable in plot
# area to sample from:
sample_area <- st_intersection(ch, laea_buff)
# sample above area, all within 10km of a point and inside the `ch` polygon
points <- st_sample(sample_area, size = 10)
#plotting:
ggplot() +
geom_sf(data = points, color = 'red') +
geom_sf(data = laea_buff, color = 'black', fill = NA) +
geom_sf(data = ch, color = 'black', fill = NA) +
geom_sf(data = sample_area, color = 'pink', fill = NA) +
geom_sf(data = df.laea, color = 'black', size = .5)
Created on 2023-02-14 by the reprex package (v2.0.1)
As a comment on the nice answer by shs: it is possible to first use a sf::st_combine() call on the df.laea object & merge the 10 points to a single multipoint geometry.
This, when buffered, will work as an input for the necessary sf::st_difference() call to form a sampling area with holes, removing the need for a for cycle / map & reduce call.
# Packages
library(sf)
library(ggplot2)
# Create some points
set.seed(1)
df <- data.frame(
gr = c(rep("a",5),rep("b",5)),
x = rnorm(10),
y = rnorm(10)
)
df <- st_as_sf(df,coords = c("x","y"),remove = F, crs = 4326)
df.laea = st_transform(
df,
crs = "+proj=laea +x_0=4600000 +y_0=4600000 +lon_0=0.13 +lat_0=0.24 +datum=WGS84 +units=m"
)
# merge 10 points to 1 multipoing
mod_laea <- df.laea %>%
st_combine()
# sampling area = difference between hull and buffered points
sampling_area <- mod_laea %>%
st_convex_hull() %>%
st_difference(st_buffer(mod_laea, 10000))
# sample over sampling area
sampled_points <- st_sample(sampling_area, 10)
# a visual overview
ggplot() +
geom_sf(data = sampling_area, fill = "white", color = "black") +
geom_sf(data = df.laea, color = "black") +
geom_sf(data = sampled_points, color = "red", pch = 4)

ggplot gridded SpatialPolygonsDataFrame producing odd triangles and subsetting data based on point data

Using the code below I can plot the following:
This code is adapted from here
As you can see there are few issues with the plot. I am struggling to
Remove weird lines in plot
Only plot cells (grids) where there are data
Plot ID (see gridSpatialPolygons$values) on top of the grid cell
I realise there are a few points to this question but I hope one solution solves all.
# Load libraries
library(sp)
library(raster)
library(ggplot2)
# Projection
wgs.84 <- CRS("+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0")
# Load data
x <- c(76.82973, 76.82972, 76.82969, 76.83076, 76.83075, 76.83071, 76.83129, 76.83126, 76.83125)
y <- c(28.26734, 28.26644, 28.26508, 28.26778, 28.26733, 28.26507, 28.26912, 28.26732, 28.26687)
z <- c(-56.7879, -58.22462, -58.4211, -55.75333, -58.55153, -56.38619, -56.11011, -58.17415, -59.77212)
# Create data frame
dataset <- data.frame("LONGITUDE" = x, "LATITUDE" = y, "VALUES" = z)
# Create SpatialPointsDataFrame object
datasetSP <- SpatialPointsDataFrame(coords = dataset[,c(1,2)], data = data.frame("id" = 1:nrow(dataset), "values" = dataset$VALUES), proj4string = wgs.84)
# Extent
extentDatasetSP <-extent(datasetSP)
# Make grid options
# Cell size (map units)
xCellSizeGrid <- 0.001
yCellSizeGrid <- 0.001
# Grid
grid <- GridTopology(cellcentre.offset = c(extentDatasetSP#xmin, extentDatasetSP#ymin),
cellsize = c(xCellSizeGrid, yCellSizeGrid),
cells.dim = c(3, 7))
# Create SpatialGrid object
gridSpatial <- SpatialGrid(grid = grid, proj4string = wgs.84)
# Convert to SpatialPixels object
gridSpatialPixels <- as(gridSpatial, "SpatialPixels")
# Convert to SpatialPolygons object
gridSpatialPolygons <- as(gridSpatialPixels, "SpatialPolygons")
# Add 'id' and 'values' to every polygon
gridSpatialPolygons$id <- 1:nrow(coordinates(gridSpatialPolygons))
gridSpatialPolygons$values <- paste("Gridvalue", 1:nrow(coordinates(gridSpatialPolygons)), sep = ":")
# Get attributes from polygons
samplePointsInPolygons2 <- datasetSP %over% gridSpatialPolygons
ggplot(gridSpatialPolygons, aes(x = long, y = lat)) +
geom_polygon(color = "red") +
geom_point(data = dataset,
aes(x = LONGITUDE,
y = LATITUDE))
When it comes to spatial objects, ggplot2 (and tidyverse in general) seems to play nicer with sf than sp. The advice below is taken from one of the help files in the associated broom package:
Note that the sf package now defines tidy spatial objects and is the
recommended approach to spatial data. sp tidiers are likely to be
deprecated in the near future in favor of sf::st_as_sf(). Development
of sp tidiers has halted in broom.
Things should be fairly straightforward after conversion to sf.
library(dplyr)
sf::st_as_sf(gridSpatialPolygons) %>%
filter(id %in% samplePointsInPolygons2$id) %>% # keep only grid cells with data
ggplot() +
geom_sf(colour = "red") +
geom_sf_text(aes(label = values), # label cells
nudge_y = 0.0003, colour = "grey40") +
geom_point(data = dataset,
aes(x = LONGITUDE,
y = LATITUDE))

R: Polar map projection of polygon data

What I have:
points in the arctic and antarctic
raster data from various geophysical entities in arctic and antarctic
What I want:
A map in stereographic or any other polar projection with background map or coastlines, cropped to the extent of the points. In other words: A map like above with base map of my own choice.
What I did so far:
I loaded all the data (including land surface data from naturalearthdata; see MWE), projected them into stereographic and plotted that. The result including the polygon data looks then like this:
My MWE:
library(raster)
library(sf)
library(ggplot2)
library(rgdal)
# file load ---------------------------------------------------------------
# sea ice raster data
if (!file.exists("seaiceraster.tif")) {
url = "https://seaice.uni-bremen.de/data/smos/tif/20100514_hvnorth_rfi_l1c.tif"
download.file(url, destfile = 'seaiceraster.tif')
}
si.raster = raster::raster('seaiceraster.tif')
# land surface shapefile
if (!file.exists("110m-admin-0-countries")) {
url_land = "https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/physical/ne_10m_land.zip"
download.file(url_land, destfile = "110m-admin-0-countries")
unzip("110m-admin-0-countries")
}
world_shp = rgdal::readOGR("ne_10m_land.shp")
# points
p.data = structure(
list(
Lat = c(
73.0114126168676,70.325555278764,77.467797903163,
58.6423827457304,66.3616310851294,59.2097857474643,
75.3135274436283,60.1983078512275,72.6614399747201,
61.1566678672946,73.0822309615673,55.7759666826898,
75.1651656433833,69.0130753414173,62.3288262448589
),
Lon = c(
-59.9175490701543,-80.1900239630732,-40.4609968914928,
-61.0914448815381,-60.0703668488408,-21.027205418284,
-100.200463810276,-74.861777073788,-55.1093773178206,
-29.4108649230234,-64.5878251008461,-36.5343322019187,
-31.647365623387,-67.466355105829,-64.1162329769077
)
),
row.names = c(
1911L, 592L,2110L,3552L,3426L,1524L,635L,4668L,
3945L,2848L,3609L,36L,4262L,3967L,2725L
),
class = "data.frame"
)
p = sf::st_as_sf(p.data, coords = c("Lon", "Lat"),
crs = "+init=epsg:4326")
# project -----------------------------------------------------------------
polar.crs = CRS("+init=epsg:3995")
si.raster.proj = projectRaster(si.raster, crs = polar.crs)
world_shp.proj = sp::spTransform(world_shp, polar.crs)
p.proj = sf::st_transform(p, polar.crs)
# preparation -------------------------------------------------------------
AG = ggplot2::fortify(world_shp.proj)
# make raster to data.frame
si.raster.df = si.raster.proj %>%
raster::crop(., p.proj) %>%
raster::rasterToPoints(., spatial = TRUE) %>%
as.data.frame(.)
colnames(si.raster.df) = c("val", "x", "y")
# plot --------------------------------------------------------------------
ggplot() +
# geom_polygon(data = AG, aes(long, lat, group = group)) + # un-comment to see
geom_raster(data = si.raster.df, aes(x = x, y = y, fill = val)) +
geom_sf(data = p.proj, color = "green", size = 3)
I've changed the workflow in your example a bit to add the stars package for the sea ice data, but I think it should get you what you're looking for. You'll need to adjust the crop size to expand it a little, as the points p are right on the edge of the plotted area. st_buffer might help with that.
I used the crs from the seaicebuffer.tif file for all of the objects.
The .tif file has a crs that I'm not able to easily transform on my computer. It seems to be able to use meters as a lengthunit and might be a polar stereographic (variant B) projection. The points & world data don't seem to have a problem transforming to it though, which is why I've used it throughout.
library(raster)
library(sf)
library(ggplot2)
library(rgdal)
library(stars)
si <- stars::read_stars('seaiceraster.tif')
world_sf = rgdal::readOGR("ne_10m_land.shp") %>%
st_as_sf() %>%
st_transform(st_crs(si))
# p <- ... same as example and then:
p <- st_transform(p, st_crs(si))
# get a bounding box for the points to crop si & world.
p_bbox <- st_bbox(p) %>%
st_as_sfc() %>%
st_as_sf() %>%
st_buffer(100000)
# crop si & world_sf to an area around the points (p)
world_cropped <- st_crop(world_sf, p_bbox)
si_cropped <- st_crop(si, p_bbox)
#Plot
ggplot() +
geom_sf(data = world_cropped,
color = 'black',
fill = 'NA',
size = .2) +
geom_stars(data = si_cropped) +
geom_sf(data = p, color = 'red') +
scale_fill_continuous(na.value = 0)
Ugly hack for the southern .tif that stars reads as factors:
si <- stars::read_stars('20150324_hvsouth_rfi_l1c.tif', NA_value = 0 )
si$"20150324_hvsouth_rfi_l1c.tif" <- as.numeric(si$"20150324_hvsouth_rfi_l1c.tif")
ggplot() + geom_stars(data = si)

Overlay raster layer on map in ggplot2 in R?

I am trying to overlay a raster layer onto a map in ggplot. The raster layer contains likelihood surfaces for each time point from a satellite tag. I also want to set cumulative probabilities(95%, 75%, 50%) on the raster layer.
I have figured out how to show the raster layer on the ggplot map, but the coordinates are not aligned with one another. I tried making each have the same projection but it does not seem to be working... I want them both to fit the boundaries of my model (xmin = 149, xmax = 154, ymin = -14, ymax = -8.75
Attached is my r code and the figure result:
#load data
ncname <- "152724-13-GPE3"
ncfname <- paste(ncname, ".nc", sep = "")
ncin <- nc_open(ncfname)
StackedObject<-stack("152724-13-GPE3.nc", varname = "monthly_residency_distributions")
MergedObject<-overlay(StackedObject,fun=mean )
MergedObject[is.na(MergedObject)]<-0
Boundaries<-extent(c(149, 154, -14, -8.75))
ExtendedObject<-extend(MergedObject, Boundaries)
Raster.big<-raster(ncol=1200,nrow=900,ext=Boundaries)
Raster.HR<-resample(x=ExtendedObject, y=Raster.big, method="bilinear")
Raster.HR#data#values<- Raster.HR#data#values/sum(Raster.HR#data#values)
RasterVals<-sort(Raster.HR#data#values)
Raster.breaks <- c(RasterVals[max(which(cumsum(RasterVals)<= 0.05 ))], RasterVals[max(which(cumsum(RasterVals)<= 0.25 ))], RasterVals[max(which(cumsum(RasterVals)<= 0.50 ))], 1)
Raster.cols<-colorRampPalette(c("yellow","orange","red"))
RasterCols<- c(Raster.cols(3))
#Create Map
shape2 <- readOGR(dsn = "/Users/shannonmurphy/Desktop/PNG_adm/PNG_adm1.shp", layer = "PNG_adm1")
map<- crop(shape2, extent(149, 154, -14, -8.75))
projection(map)<- CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
p <- ggplot() + geom_polygon(data = map, aes(x = long, y = lat, group = group), color = "black", size = 0.25) + coord_map()
projection(Raster.HR)<- CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
#plot raster and ggplot
par(mfrow=c(1,1))
plot(p)
par(mfrow=c(1,1), new = TRUE)
plot(Raster.HR, col=RasterCols, breaks=Raster.breaks, legend = NULL, bbox(map))
Please let me know if there is another package/line of code I should be using to do this! Appreciate any help
Ok I understand. You want to plot multiple raster layers on the ggplot or you want that the raster object is over your background polygon object. The problem with rasterVis::gplot is that it directly plot the raster and does not allow to add another one under or over. You remind me that I already had this need and modified function gplot to retrieve the data as a tibble so that you can then play with it as much as you want with dplyr and then ggplot2. Thanks for the reminder, I added it in my current github library for later use!
Let's use a reproducible example to show this function:
Create datasets
Create a map of the world as a Raster to be use as background Raster map
Create a raster of data, here a distance from a point (limited to a maximum distance)
The code:
library(raster)
# Get world map
library(maptools)
data(wrld_simpl)
# Transform World as raster
r <- raster(wrld_simpl, res = 1)
wrld_r <- rasterize(wrld_simpl, r)
# Lets create a raster of data
pt1 <- matrix(c(100,0), ncol = 2)
dist1 <- distanceFromPoints(r, pt1)
values(dist1)[values(dist1) > 5e6] <- NA
plot(dist1)
# Plot both
plot(wrld_r, col = "grey")
plot(dist1, add = TRUE)
Function to extract (part of) raster values and transform as a tibble
#' Transform raster as data.frame to be later used with ggplot
#' Modified from rasterVis::gplot
#'
#' #param x A Raster* object
#' #param maxpixels Maximum number of pixels to use
#'
#' #details rasterVis::gplot is nice to plot a raster in a ggplot but
#' if you want to plot different rasters on the same plot, you are stuck.
#' If you want to add other information or transform your raster as a
#' category raster, you can not do it. With `SDMSelect::gplot_data`, you retrieve your
#' raster as a tibble that can be modified as wanted using `dplyr` and
#' then plot in `ggplot` using `geom_tile`.
#' If Raster has levels, they will be joined to the final tibble.
#'
#' #export
gplot_data <- function(x, maxpixels = 50000) {
x <- raster::sampleRegular(x, maxpixels, asRaster = TRUE)
coords <- raster::xyFromCell(x, seq_len(raster::ncell(x)))
## Extract values
dat <- utils::stack(as.data.frame(raster::getValues(x)))
names(dat) <- c('value', 'variable')
dat <- dplyr::as.tbl(data.frame(coords, dat))
if (!is.null(levels(x))) {
dat <- dplyr::left_join(dat, levels(x)[[1]],
by = c("value" = "ID"))
}
dat
}
Plot multiple rasters in ggplot
You can use gplot_data to transform any raster as a tibble. You are then able to add any modification using dplyr and plot on ggplot with geom_tile. The interesting point is that you can use geom_tile as many time as you want with different raster data, provided that fill option is comparable. Otherwise, you can use the trick below to remove NA values in the background raster map and use a unique fill colour.
# With gplot_data
library(ggplot2)
# Transform rasters as data frame
gplot_wrld_r <- gplot_data(wrld_r)
gplot_dist1 <- gplot_data(dist1)
# To define a unique fill colour for the world map,
# you need to remove NA values in gplot_wrld_r which
# can be done with dplyr::filter
ggplot() +
geom_tile(data = dplyr::filter(gplot_wrld_r, !is.na(value)),
aes(x = x, y = y), fill = "grey20") +
geom_tile(data = gplot_dist1,
aes(x = x, y = y, fill = value)) +
scale_fill_gradient("Distance",
low = 'yellow', high = 'blue',
na.value = NA) +
coord_quickmap()
Plot raster over polygons
Of course, with a background map as a polygon object, this trick also let you add your raster over it:
wrld_simpl_sf <- sf::st_as_sf(wrld_simpl)
ggplot() +
geom_sf(data = wrld_simpl_sf, fill = "grey20",
colour = "white", size = 0.2) +
geom_tile(data = gplot_dist1,
aes(x = x, y = y, fill = value)) +
scale_fill_gradient("Distance",
low = 'yellow', high = 'blue',
na.value = NA)
EDIT: gplot_data is now in this simple R package: https://github.com/statnmap/cartomisc

google map from dismo::gmap() and ggplot2

I obtained a map with the function dismo::gmap() and want to plot it with ggplot2 because I want to add different feautures using geom_point and other ggplot functions. I prefer to use dismo::gmap instead of ggmap::get_map() to download the google map layer. This is because dismo::gmap(), unlike ggmap::get_map(), returns a raster layer from package raster including complete CRS information and therefore is should be possible to modify the projection of the layer.
> head(data_info$latitude, 20)
#[1] 49.11306 49.39333 48.78083 51.85000 53.57361 50.67806 52.69083 52.21389 53.46361 50.99917 53.99750 53.54528 53.61417 48.00556 48.01306 53.45000
#[17] 51.93667 54.53083 51.95500 54.29639
> head(data_info$longitude, 20)
#[1] 13.134722 12.323056 13.803889 12.177778 14.143611 13.175833 12.649444 13.454167 11.629722 10.906111 11.415556 8.426944 7.160000 11.123889 10.786111
#[16] 12.766667 11.987222 13.091389 10.967500 13.684167
e = extent(-14 , 58 , 28 , 64)
mapImageData2 <- gmap(e, type = c("terrain"), lonlat = TRUE,
path = "&style=feature:all|element:labels|visibility:off&style=feature:administrative.country|element:geometry.stroke|visibility:off")
mapImageData2_proj <- projectExtent(mapImageData2, crs = "+proj=utm +zone=31 +datum=WGS84")
# plot the points on the map
ggplot(mapImageData2_proj, extent = "device") +
geom_point(inherit.aes = FALSE, aes(x = data_info$longitude, y = data_info$latitude),
data = gps, colour = "red", size = 1, pch = 20)
After trying this, I get the following error:
Error: ggplot2 doesn't know how to deal with data of class
RasterLayer
If I try this
plot(mapImageData2_proj)
Error in .plotraster2(x, col = col, maxpixels = maxpixels, add = add,
: no values associated with this RasterLayer
There are two issues in this question. One is how to get ggplot2 to plot a Raster* object. The other is how to reproject a raster while retaining its values.
The OP contains the code
library(dismo)
e = extent(-14 , 58 , 28 , 64)
mapImageData2 <- gmap(e, type = c("terrain"), lonlat = TRUE,
path = "&style=feature:all|element:labels|visibility:off&style=feature:administrative.country|element:geometry.stroke|visibility:off")
If we run this and then do plot(mapImageData2) we get a nice plot. The OP then runs
mapImageData2_proj <- projectExtent(mapImageData2, crs = "+proj=utm +zone=31 +datum=WGS84")
Now if we run plot(mapImageData2_proj) we get an error! That's because projectExtent returns a RasterLayer with no values. We need to use projectRaster() instead. See ?projectExtent for details. So we run:
mapImageData2_proj <- projectRaster(mapImageData2, crs = "+proj=utm +zone=31 +datum=WGS84")
plot(mapImageData2_proj)
Now we see the reprojected map. Progress! But we still can't plot mapImageData2_proj using ggplot2, because ggplot2 doesn't know how to handle a Raster* object. We need to convert our raster to a dataframe. There are a few ways to do this, but without loading any additional packages, a good option is raster::rasterToPoints(). For example:
myPoints <- raster::rasterToPoints(myRaster)
myDataFrame <- data.frame(myPoints)
colnames(myDataFrame) <- c("Longitude", "Latitude", "Values")
ggplot(data=myDataFrame, aes_string(y = "Latitude", x = "Longitude")) +
geom_raster(aes(fill = Values))
So to put it all together in the OP's example:
library(dismo)
e = extent(-14 , 58 , 28 , 64)
mapImageData2 <- gmap(e, type = c("terrain"), lonlat = TRUE,
path = "&style=feature:all|element:labels|visibility:off&style=feature:administrative.country|element:geometry.stroke|visibility:off")
plot(mapImageData2)
mapImageData2_proj <- projectRaster(mapImageData2, crs = "+proj=utm +zone=31 +datum=WGS84")
plot(mapImageData2_proj)
myRaster <- mapImageData2_proj
myPoints <- raster::rasterToPoints(myRaster)
myDataFrame <- data.frame(myPoints)
colnames(myDataFrame) <- c("X", "Y", "Values")
ggplot(data=myDataFrame, aes_string(y = "Y", x = "X")) +
geom_raster(aes(fill = Values))
To directly plot a Raster* object in ggplot, you can use the library RasterVis as follows:
r <- raster(system.file("external/test.grd", package="raster"))
s <- stack(r, r*2)
names(s) <- c('meuse', 'meuse x 2')
library(ggplot2)
theme_set(theme_bw())
gplot(s) + geom_tile(aes(fill = value)) +
facet_wrap(~ variable) +
scale_fill_gradient(low = 'white', high = 'blue') +
coord_equal()
As you see, we use gplot and not ggplot.
This function is for Raster* objects as it allows to load only a part of the Raster* object in RAM. You can even choose the maximum number of pixels to load on the map with gplot(s, maxpixels=50000).
Indeed, I recommend not to transform your Raster as points, because, if your raster is huge, you will not be able to load it in the RAM...

Resources