-1
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?

IRTFM
  • 258,963
  • 21
  • 364
  • 487

1 Answers1

8

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.

Community
  • 1
  • 1
hrbrmstr
  • 77,368
  • 11
  • 139
  • 205
  • Thank you very much for your help! A case in my data can only have one out of 16 values (1, 2, 3, ..., 16) on the x-axis. Unfortunately, it didn't work in my data: I receive several vertical lines on the plot (instead of one at the maximum), and they are always on my x-values (e.g. at x = 3). What went wrong? And how can I make the console to output the x-value of the curve maximum? – Magnus Oresand Jul 05 '15 at 15:58
  • can you provide a `dput(data)`? – hrbrmstr Jul 05 '15 at 16:10
  • With my data and the above described code I receive two curve maximums at the x-values of 8 and 10. However the fit line's maximum is not at either of the two values. How can I draw the fit line? 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") Thanks! – Magnus Oresand Jul 13 '15 at 14:20
  • I've updated the answer with the two plots using your data. Did I make a mistake in the plotting? – hrbrmstr Jul 13 '15 at 14:54
  • The plotting is nice! How can one retrieve the exact x-value of the curve maximum? – Magnus Oresand Jul 13 '15 at 17:02
  • apologies. i thought it was more obvious than it turned out to be. answer: updated. – hrbrmstr Jul 13 '15 at 17:29