Search code examples
ggplot2plotdata-visualizationcurve-fittingfacet-grid

How to extract stat_smooth curve maxima in gpplot panel (facet_grid)?


I have created this plot with 18 grids using facet_grid command and two different fitting equations (for Jan - Apr, and May - Jun). I have two things that I need help with:

  1. (may sound obvious, but) I haven't been able to find on the internet working codes extract a curve maximum for a stat_smooth fit. I'd appreciate if someone could show and explain what the codes mean. This is the closest I could find, but I am not sure what it means:
gb <- ggplot_build(p1)

curve_max <- gb$data[[1]]$x[which(diff(sign(diff(gb$data[[1]]$y)))==-2)+1]
  1. How to add a vertical line to indicate max value on each curve?

Data file (rlc2 <- read_excel)

Plot

plot <- ggplot(rlc2, aes(par, etr, color=month, group=site))+
  geom_point()+
  stat_smooth(data = subset(rlc2, rlc2$month!="May" & rlc2$month!="Jun"),
              method = "glm",
              formula = y ~ x + log(x),
              se = FALSE,
              method.args = list(family = gaussian(link = "log"), start=c(a=0, b=0, c=0)))+
  stat_smooth(data = subset(rlc2, rlc2$month=="May" | rlc2$month=="Jun"),
              method = "nlsLM",
              formula = y ~ M*(1 - exp(-(a*x))),
              se = FALSE,
              method.args = list(start=c(M=0, a=10)))+
  facet_grid(rows = vars(month), cols = vars(site))
plot

field_rlc_plot

Any other advice are also welcome. I am educated as programmer so my codes are probably a bit messy. Thank you for helping.


Solution

  • Try this:

    First, fit the data and extract the maximum of the fit.

    my.fit <- function(month, site,  data) {
      fit <- glm(formula = etr ~ par + log(par),
          data = data,
          family=gaussian(link = "log")
          )
      #arrange  the dersired output in a tibble
      tibble(max  = max(fit$fitted.values),
             site = site,
             month = month)
    }
    
    #Apply a custom function `my.fit` on each subset of data
    #according to month and site using the group_by/nest/map method
    # the results are rowbinded and returned in a data.frame
    
    my.max<-
      rlc2 %>% 
      dplyr::group_by(month, site) %>% 
      tidyr::nest() %>% 
      purrr::pmap_dfr(my.fit)
    

    Next, join the results back on your data and plot a geom_line

    rlc2  %>% 
      dplyr::left_join(my.max) %>% 
      ggplot(aes(x = par, y = etr))+
      geom_point()+
      stat_smooth(data = subset(rlc2, rlc2$month!="May" & rlc2$month!="Jun"),
                  method = "glm",
                  formula = y ~ x + log(x),
                  se = FALSE,
                  method.args = list(family = gaussian(link = "log"), start=c(a=0, b=0, c=0)))+
      stat_smooth(data = subset(rlc2, rlc2$month=="May" | rlc2$month=="Jun"),
                  method = "nlsLM",
                  formula = y ~ M*(1 - exp(-(a*x))),
                  se = FALSE,
                  method.args = list(start=c(M=0, a=10)))+
      geom_line(aes(y=max), col="red")+
      facet_grid(rows = vars(month), cols = vars(site))
    

    enter image description here