Search code examples
rggplot2rastergeotiffcolor-palette

Plotting a GeoTIFF raster in R


I am trying to plot a gridded population count GeoTIFF raster downloaded from here.

library(raster)

#----------------------------#
# Set your working directory #
#----------------------------#

setwd(dirname(rstudioapi::getActiveDocumentContext()$path)) # RStudio IDE preferred

getwd() # Path to your working directory

# Import the GeoTIFF file into R workspace

WorldPop <- raster("nga_ppp_2020_1km_Aggregated_UNAdj.tif")

WorldPop

#---------------------------#
# Data plotted in log-scale #
#---------------------------#

tempcol <- colorRampPalette(c("lightblue", "skyblue", "blue", "yellow", "orange", "red", "darkred"))

plot(log(WorldPop), main = "2020 UN-Adjusted Population Count (log-scale) \n (each grid cell is 1 km x 1 km)", col=tempcol(100), legend.width=2, legend.shrink=1, legend.args=list(text='log(Persons)', side=4, font=2, line=2.5, cex=0.8), axes=T)

#--------------------------------#
# Data plotted in absolute-scale #
#--------------------------------#

plot(WorldPop, main = "2020 UN-Adjusted Population Count (absolute-scale) \n (each grid cell is 1 km x 1 km)", col=tempcol(100), legend.width=2, legend.shrink=1, legend.args=list(text='Persons', side=4, font=2, line=2.5, cex=0.8), axes=T)

Plot 1 (log-scale)

enter image description here

Plot 2 (absolute-scale)

enter image description here

I like the Plot 1 (data in log-scale) but Plot 2 (data in absolute-scale) is not showing any variations in color. How can I make the plot of data in absolute-scale look similar to the one in log-scale?

I am open to using other packages (ggplot2 etc.) or other color palates as long as my plot can distinguish densely populated areas from rural areas. When I used a different GIS tool called Panoply my favorite color palate was something called seminf-haxby.cpt (found here). It looks something like this

enter image description here

I am trying to replicate that in R but the plot in absolute-scale isn't looking good. Any tips or advice for plotting tif rasters in R?


Solution

  • You can set breaks, something like this:

    Example data

    url <- "https://data.worldpop.org/GIS/Population/Global_2000_2020_1km_UNadj/2020/NGA/nga_ppp_2020_1km_Aggregated_UNadj.tif"
    fname <- basename(url)
    if (!file.exists(fname)) download.file(url, fname, mode="wb")
    

    Solution

    library(terra)
    r <- rast(fname)
    plot(r, col=rev(rainbow(10, end=0.7)), breaks=c(0, 10, 25, 50, 100, 250, 1000, 100000))
    

    enter image description here

    Now your second question (it is better to not ask two rather different questions at the same time).

    The function below extracts the colors from the palette image in your question, and should also work for other palette images organized like yours.

    getPal <- function(f) {
        x <- rast(f)
        u <- unique(values(x))
        hex <- rgb(u[,1], u[,2], u[,3], maxColorValue = 255)
        colorRampPalette(hex)
    }
    
    pal <- getPal("https://i.sstatic.net/E4d85.png")
    
    par(mar=c(0,0,0,0))
    barplot(rep(1, 25), col=pal(25), space=0)
    

    enter image description here

    An alternative way to apply breaks is to first use classify. I remove the first color (white)

    x <- classify(r, c(0, 10, 25, 50, 100, 250, 1000, 100000))
    plot(x, col=pal(8)[-1])
    

    enter image description here

    You could change the labels, for example like this

    levs <- levels(x)[[1]]
    levs[7] <- "> 1000"
    levels(x) <- levs
    

    To use this palette in your R code you can create it like this (remove '#FFFFFF' if you do not want to start with white)

    ramp <- c('#FFFFFF', '#D0D8FB', '#BAC5F7', '#8FA1F1', '#617AEC', '#0027E0', '#1965F0', '#0C81F8', '#18AFFF', '#31BEFF', '#43CAFF', '#60E1F0', '#69EBE1', '#7BEBC8', '#8AECAE', '#ACF5A8', '#CDFFA2', '#DFF58D', '#F0EC78', '#F7D767', '#FFBD56', '#FFA044', '#EE4F4D')
    pal <- colorRampPalette(ramp)