rggplot2interpolationlogistic-regressiongeom-raster

Interpolate between logistic regressions with different slope in ggplot geom_raster


Using a simple logistic growth model, I want to plot a contour/gradient based plot showing how the growth parameter (r) changes the slope and asymptotes of the curve.

I want to interpolate between the curves plotted instead of just showing a set of lines.

So I have tried the following:

#Using these packages
library(ggplot2)
library(tidyr)

# The logistic function applied to a vector of time steps (t)
# K is carrying capacity - asymptote
# N0 is initial population density
# r is growth rate - slope
LogGr <- function(r,K,N0,t){
  d <- vapply(t,function(t) K/(1+(K/N0-1)*exp(-r*t)),numeric(1))
}

# time steps - daily over 4 years
t<-1:(365*4)

# r values - lots of them
r <- as.list(seq(0,0.1,0.001))

# using lapply to run each growth parameter - faster than for loop
ld <- lapply(r,LogGr,K=1,N0=0.00001,t=t)

# create data frame - col of population densities (N) for each r value
df <- data.frame(matrix(unlist(ld), nrow=length(t), byrow=F))
# Add time column (days)
df$Days <- t
# Rename cols for ease of viewing
colnames(df) <- c(as.character(as.vector(r)),"Days")

# Transform to long data format - facilitate ggplot colouring
Data <- gather(df,key=Gr,value=N,-Days)

# GGplot geom_raster plot
# My problem lies here somewhere - I may be misunderstanding the interpolate param.
ggplot(Data,aes(x=Days,y=round(N,3)))+
  geom_raster(aes(fill=as.numeric(Gr)),interpolate=T)+
  labs(y="Population Density",col="Growth Rate")

I want the colour to interpolate between the curves.

EDIT: After increasing the amount of r values in the given range to seq(0,0.1,0.00001) I was able to produce a raster with interpolation using the above code.

So this question has become 'How to you control how far the interpolation in geom_raster will spread? But this may be a repeat question now. Update to come soon.


Solution

  • I would recommend using stat_summary_hex() geom for the task. I provide a scaling function to let you play with the fill scale. Input like viridis::scale_fill_viridis(rescaler = scale_fn) if needed.

    scale_fn <- function(x, to = c(0, 1), from = NULL) {
        ifelse(x<max(x)/10, 
               scales::rescale(x,
                               to = to,
                               from = c(0, max(x)/10)),
               1)}
    
    ggplot(Data,aes(x=Days,y=round(N,3)))+
      stat_summary_hex(aes(z=as.numeric(Gr)))+
      labs(y="Population Density",col="Growth Rate")+
      viridis::scale_fill_viridis()
    

    enter image description here

    To use geom_raster you should have a value for each grid point. The interpolation parameter will smooth the valie betweein each raster-tile so the resulting image looks smooth.

    try the following to see the difference:

    ggplot(faithfuld, aes(waiting, eruptions)) +
     geom_raster(aes(fill = density), interpolate = TRUE)