Search code examples
rggplot2curve-fittingbest-fit-curvecurvesmoothing

calculate x-value of curve maximum of a smooth line in R and ggplot2


data <- dput(data): structure(list(x = 1:16, y = c(-79.62962963, -84.72222222, -88.42592593, -74.07407407, -29.62962963, 51.38888889, 79.62962963, 96.2962963, 87.96296296, 88.42592593, 73.14814815, 12.96296296, -63.42592593, -87.03703704, -87.5, -87.96296296)), .Names = c("x", "y"), row.names = c(NA, 16L), class = "data.frame")

I calculated in R with ggplot2 a smooth line for my dataset:

p1 <- ggplot(data, aes(x=x(°), y=(%)))

library(splines)
library(MASS)
(p2 <- p1 + stat_smooth(method = "lm", formula = y ~ ns(x,3)) +
  geom_point()
)

How can I calculate the x-value of the curve maximum of the smooth line?


Solution

  • You'll need to do some math on the resultant data.frame calculated by stat_smooth:

    library(ggplot2)
    library(splines)
    library(MASS)
    
    data <- structure(list(x = 1:16, 
                           y = c(-79.62962963, -84.72222222, -88.42592593, 
                                 -74.07407407, -29.62962963, 51.38888889, 
                                 79.62962963, 96.2962963, 87.96296296, 
                                 88.42592593, 73.14814815, 12.96296296, 
                                 -63.42592593, -87.03703704, -87.5, 
                                 -87.96296296)), .Names = c("x", "y"), 
                      row.names = c(NA, 16L), class = "data.frame") 
    
    p1 <- ggplot(data, aes(x=x, y=y))
    p1 <- p1 + stat_smooth(method = "lm", formula = y ~ ns(x,3))
    p1 <- p1 + geom_point()
    p1
    

    enter image description here

    gb <- ggplot_build(p1)
    
    exact_x_value_of_the_curve_maximum <- gb$data[[1]]$x[which(diff(sign(diff(gb$data[[1]]$y)))==-2)+1]
    
    p1 + geom_vline(xintercept=exact_x_value_of_the_curve_maximum)
    
    exact_x_value_of_the_curve_maximum
    [1] 9.164557
    

    enter image description here

    There are more robust ways as well, but you still need the ggplot_build part to get to the data.