Warning: package 'terra' was built under R version 4.4.2
Warning: package 'tidyterra' was built under R version 4.4.2
Warning: package 'terra' was built under R version 4.4.2
Warning: package 'tidyterra' was built under R version 4.4.2
For the most part, visualizing raster data follows the same rules as other continuous datasets. Here, we’ll use GEBCO data centered around Cebu City in the Phillippines.
cebuDEM<-rast("data/cebu_DEM.tif")Raster data behaves similarly to the 2D bin or heatmap objects we’ve seen before, the primary aesthetic attribute to be used here is fill color. Therefore, all of the scale_fill_* functions apply here. For example, scale_fill_gradient will plot between low and high values:
ggplot() +
geom_spatraster(data=cebuDEM) +
scale_fill_gradient(low="blue",high="red") +
theme_minimal() +
labs(fill="Elevation (m)")
This isn’t particularly revealing. Alternatively, we can use scale_fill_gradient2 to use divergent colors, here using a midpoint of 0m to split the gradient at sea level:
ggplot() +
geom_spatraster(data=cebuDEM) +
scale_fill_gradient2(low="red",mid="yellow",high="darkgreen",midpoint=0) +
theme_minimal() +
labs(fill="Elevation (m)")
That’s a little clearer. Other palettes work here as well. Here’s a how it looks with viridis, using the magma palette:
ggplot() +
geom_spatraster(data=cebuDEM) +
scale_fill_viridis_c(option="magma") +
theme_minimal() +
labs(fill="Elevation (m)")
By the way, if we want to generate a summary statistic about the cell values in our raster, we can access these using the values function:
max(values(cebuDEM))[1] 925
min(values(cebuDEM))[1] -1932
This can be useful for setting
elevations<-values(cebuDEM)
ggplot(data=elevations,aes(cebu_DEM))+
geom_histogram()`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

With elevation or other continuous data, we may want to apply colors that correspond to particular intervals. One way to do this us using the rescale from the scales package:
library(scales)
Attaching package: 'scales'
The following object is masked from 'package:terra':
rescale
The following object is masked from 'package:purrr':
discard
The following object is masked from 'package:readr':
col_factor
mn<-min(values(cebuDEM))
mx<-max(values(cebuDEM))
rescaledElev<-rescale(c(mn,-1000,-500,0,500,mx),to=c(0,1))Here what we’ve done is first create variables storing the minimum and maximum values from the raster. Then we used rescale to create a vector of values between that minimum and maximum, but scaled between 0 and 1. We can use these to control the look of the plot plot with scale_fill_gradientn:
ggplot() +
geom_spatraster(data=cebuDEM) +
scale_fill_gradientn(colors=c("darkblue","blue","skyblue","darkgreen","lightgreen"),values=rescaledElev)
This looks OK, but since maps often have distinct color boundaries between water and land, we might want to indicate those colors with blue. s, so we can set a hard boundary by adding two values after the minimum: -1 and 1
rescaledElev<-rescale(c(mn,-1000,-500,-1,0,1,500,mx),to=c(0,1))Now when we run the ggplot, we can add two new colors: dark blue and blue, so our values will scale up to blue shades only through to 361
ggplot() +
geom_spatraster(data=cebuDEM) +
scale_fill_gradientn(colors=c("darkblue","blue","skyblue","darkgreen","lightgreen"),values=rescaledElev)+
theme_minimal() +
labs(fill="Elevation (m)")
At this point, we could continue to modify the colors and rescaled intervals until we get the precise look we want, but it looks much more like a map of the terrain and waterways around Cebu City. The same principles work for multilayer rasters. For example, we can apply these individually:
ggplot() +
geom_spatraster(data=turkanaRain$turkanaRain_4) +
scale_fill_distiller(palette = "RdBu",direction=1) +
theme_minimal() +
labs(fill="Precipitation \n(mm)")
Or we can plot values across multiple rasters using facet_wrap:
ggplot() +
geom_spatraster(data=turkanaRain4) +
facet_wrap(~lyr) +
scale_fill_distiller(palette = "RdBu",direction=1,na.value="black")+
theme_minimal() +
labs(fill="Precipitation \n(mm)")
Note that bit at the end where it reads na.values="black". This can be used in any scale_color_* or scale_fill_* function to account data points that have NA values. It’s important to make sure that your NA values are colored using a value that does not appear in your scale. However, here we have no NA values, so there are no black cells.