Search code examples
rfunctionggplot2statgeom-area

Is there a way to fix these blank gaps between areas in ggplot?


I have a problem with drawing coloured areas behind the plot of a Normal Distribution. I desire to achieve something like this: enter image description here

but without the blank gaps. My code is

normal <- function(mu, sigma, x){
  1/(sigma*sqrt(2*pi))*exp(-((x-mu)/sigma)^2)
}
normal_shade1 <- function(mu, sigma, x){
  y <- normal(mu=mu, sigma=sigma, x)
  y[x < 0.5 | x > 1.5] <- NA
  return(y)
}
normal_shade2 <- function(mu, sigma, x){
  y <- normal(mu=mu, sigma=sigma, x)
  y[x < 1.5 | x > 2.5] <- NA
  return(y)
}
normal_shade3 <- function(mu, sigma, x){
  y <- normal(mu=mu, sigma=sigma, x)
  y[x < 2.5 | x > 3.5] <- NA
  return(y)
}
normal_shade4 <- function(mu, sigma, x){
  y <- normal(mu=mu, sigma=sigma, x)
  y[x < 3.5 | x > 4.5] <- NA
  return(y)
}
normal_shade5 <- function(mu, sigma, x){
  y <- normal(mu=mu, sigma=sigma, x)
  y[x < 4.5 | x > 5.5] <- NA
  return(y)
}
normal_shade6 <- function(mu, sigma, x){
  y <- normal(mu=mu, sigma=sigma, x)
  y[x < 5.5 | x > 6.5] <- NA
  return(y)
}
normal_shade7 <- function(mu, sigma, x){
  y <- normal(mu=mu, sigma=sigma, x)
  y[x < 6.5 | x > 7.5] <- NA
  return(y)
}

p2 <- ggplot(data = data.frame(x = seq(0.5,7.5,by=0.1)), aes(x)) +
  stat_function(fun=normal_shade1, geom='area', fill = '#f0f9e8', args=list(mu=4, sigma=1.6), alpha = 1) + 
  stat_function(fun=normal_shade2, geom='area', fill = '#ccebc5', args=list(mu=4, sigma=1.6), alpha = 1) + 
  stat_function(fun=normal_shade3, geom='area', fill = '#a8ddb5', args=list(mu=4, sigma=1.6), alpha = 1) + 
  stat_function(fun=normal_shade4, geom='area', fill = '#7bccc4', args=list(mu=4, sigma=1.6), alpha = 1) + 
  stat_function(fun=normal_shade5, geom='area', fill = '#4eb3d3', args=list(mu=4, sigma=1.6), alpha = 1) + 
  stat_function(fun=normal_shade6, geom='area', fill = '#2b8cbe', args=list(mu=4, sigma=1.6), alpha = 1) + 
  stat_function(fun=normal_shade7, geom='area', fill = '#08589e', args=list(mu=4, sigma=1.6), alpha = 1) + 
  stat_function(fun=normal, geom='line', args=list(mu=4, sigma=1.6), size = 0.3) + ylab("") + 
  scale_y_continuous(expand = expansion(mult = c(0, 0)), breaks = NULL) + 
  scale_x_continuous(breaks = seq(0.5,7.5,by=1), labels = ("−∞",1.5,2.5,3.5,4.5,5.5,6.5,"\U221E")) 

p2 + labs(title = "",
          x = "", y = "", fill = "Legenda") +  
  theme_set(
    theme_bw() +
      theme(
        #axis.title.x = element_text(margin = margin(15, 0, 0, 0)),
        axis.title.y = element_text(margin = margin(0, 1, 0, 0)),
        strip.text = element_text(size = 11),
        axis.text = element_text(size = 12, color = "black"),
        plot.title = element_blank(),#element_text(size = 20),
        plot.subtitle = element_text(size = 17),
        axis.title = element_blank(),#element_text(size = 20),
        axis.line.x = element_line(colour = "black", size = 0.3),
        axis.line.y = element_blank(),
        axis.text.x = element_text(size = 12, family = "Iwona"),
        axis.text.y = element_text(size = 20),
        legend.text = element_text(size = 20),
        axis.ticks = element_line(colour = "black", size = 0.3),
        legend.key = element_rect(fill = "white"),
        legend.position = "top", 
        panel.border = element_blank(),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        axis.line = element_line(colour = "black"),
        panel.background = element_rect(fill = "white")
      )
  )

I have already obtained the results that I am looking for in this image: enter image description here with a similar code. I really appreciate if anyone can help me.


Solution

  • stat_function works by sampling points along the x-axis and calculating the corresponding y-value. This is controlled by the n parameter ("Number of points to interpolate along the x axis."), which is by default 101. In your case, this is not enough, thus yielding gaps. If you increase the n to a high enough value, the gaps will be gone.

    In this case with n = 2000:

    ggplot(data = data.frame(x = seq(0.5,7.5,by=0.1)), aes(x)) +
      stat_function(fun=normal_shade1, geom='area', fill = '#f0f9e8', n = 2000, args=list(mu=4, sigma=1.6), alpha = 1) + 
      stat_function(fun=normal_shade2, geom='area', fill = '#ccebc5', n = 2000, args=list(mu=4, sigma=1.6), alpha = 1) + 
      stat_function(fun=normal_shade3, geom='area', fill = '#a8ddb5', n = 2000, args=list(mu=4, sigma=1.6), alpha = 1) +
      stat_function(fun=normal_shade4, geom='area', fill = '#7bccc4', n = 2000, args=list(mu=4, sigma=1.6), alpha = 1) +
      stat_function(fun=normal_shade5, geom='area', fill = '#4eb3d3', n = 2000, args=list(mu=4, sigma=1.6), alpha = 1) +
      stat_function(fun=normal_shade6, geom='area', fill = '#2b8cbe', n = 2000, args=list(mu=4, sigma=1.6), alpha = 1) +
      stat_function(fun=normal_shade7, geom='area', fill = '#08589e', n = 2000, args=list(mu=4, sigma=1.6), alpha = 1) +
      stat_function(fun=normal, geom='line', args=list(mu=4, sigma=1.6), size = 0.3) + ylab("") + 
      scale_y_continuous(expand = expansion(mult = c(0, 0)), breaks = NULL) + 
      scale_x_continuous(breaks = seq(0.5,7.5,by=1), labels = c("−∞",1.5,2.5,3.5,4.5,5.5,6.5,"\U221E")) 
    

    Working