Any way to get my curve plot that works in ggplot2 to work with Plotly's ggplotly? dose-response curve

I calculate a dose-response curve using the dr4pl library. Using stat_function from ggplot2, it's possible to plot this curve (along with data points) in a ggplot. Minimal reprex:

library(ggplot2)
library(dr4pl)
library(plotly)

myresponse <- data.frame("Dose"=c(16,8,4,2,1,0.5,0.25,0.125,0.062,0.031),
                         "Response"=c(98.1,95.8,91.6,90.6,89.6,80,5,22,10,-10))

myresult <- dr4pl(myresponse, dose=Dose, response=Response)

p <- ggplot(myresult$data, aes(x=Dose, y=Response))+
  geom_point() +
  scale_x_log10() +
  stat_function(fun = MeanResponse,
                args = list(theta = myresult$parameters),
                size=3)

p

I want a way to make this work in ggplotly. If I just do ggplotly(p), there is this error and plot:

Warning message:
In geom2trace.default(dots[[1L]][[1L]], dots[[2L]][[1L]], dots[[3L]][[1L]]) :
geom_GeomFunction() has yet to be implemented in plotly.
If you'd like to see this geom implemented,
Please open an issue with your example code at
Issues · plotly/plotly.R · GitHub

Can geom_smooth be modified to plot this line? I tried playing around with that route but I don't even really know where to begin.

Since you are not providing a function, you need to provide a set of x and y points. For it to look smooth and be exact, you want to have many points. So something like this may do what you want:

library(ggplot2)
library(dr4pl)

myresponse <- data.frame("Dose"=c(16,8,4,2,1,0.5,0.25,0.125,0.062,0.031),
                         "Response"=c(98.1,95.8,91.6,90.6,89.6,80,5,22,10,-10))

myresult <- dr4pl(myresponse, dose=Dose, response=Response)


p <- ggplot(myresult$data, aes(x=Dose, y=Response))+
  geom_point() +
  scale_x_log10() +
  stat_function(fun = MeanResponse,
                args = list(theta = myresult$parameters),
                size=3)


x_high_resolution <- seq(from = min(myresponse$Dose),
                         to = max(myresponse$Dose),
                         length.out = 1000)

y_high_resolution <- MeanResponse(x_high_resolution, theta = myresult$parameters)
fitted_function <- data.frame(Dose = x_high_resolution,
                              Response = y_high_resolution)

p2 <- ggplot(mapping = aes(x=Dose, y=Response))+
  geom_point(data = myresult$data) +
  scale_x_log10() +
  geom_line(data = fitted_function, size = 3)
  

patchwork::wrap_plots(p, p2)

Created on 2022-10-24 by the reprex package (v2.0.1)

You could use geom_smooth() to reduce the number of points, but that introduces new risks, as geom_smooth() is doing a lot of computations and approximations itself. So I would rather increase the number of points and use geom_line().

1 Like

Incredible solution, thank you @AlexisW !

The result allowed easy extraction of all the data points, and the final plot works with ggplotly!

I'm now going to try and understand the theta parameter a bit more.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.