I have some data where I would like to fit a nonlinear model to each subset of the data using nls, then superimpose the fitted models onto a graph of the data points using g
The ideal solution would plot the results of nls()
using ggplot
, but here's a "quick and dirty" solution based on a couple of observations.
First, you can be sure that if you use the same formula for nls()
and geom_smooth(method = "nls")
, you will get the same coefficients. That's because the latter is calling the former.
Second, using your example data, nls()
converges to the same values of Vmax and Km (different for each drug), regardless of start value. In other words, there's no need to build models using start values in the range for each individual drug. Any of the following give the same result for drug 1 (and similarly for drug 2):
library(dplyr)
# use maximum as start
df1 %>%
filter(drug == 1) %>%
nls(rate ~ Vm * Concentration/(K + Concentration),
data = .,
start = list(K = max(.$Concentration), Vm = max(.$rate)))
# use minimum as start
df1 %>%
filter(drug == 1) %>%
nls(rate ~ Vm * Concentration/(K + Concentration),
data = .,
start = list(K = min(.$Concentration), Vm = min(.$rate)))
# use arbitrary values as start
df1 %>%
filter(drug == 1) %>%
nls(rate ~ Vm * Concentration/(K + Concentration),
data = .,
start = list(K = 50, Vm = 2))
So the quickest way to plot the curves is simply to map the drug to a ggplot
aesthetic, such as color. This will construct separate nls
curves from the same start values and you can then go back to nls()
if required to get the coefficients, knowing that the models should be the same as the plot.
Using your example data file
(but don't call it file
, I used df1
):
library(ggplot2)
df1 <- structure(list(Concentration = c(500, 250, 100, 62.5, 50, 25, 12.5, 5,
500, 250, 100, 62.5, 50, 25, 12.5, 5),
drug = c(1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2),
rate = c(1.88922, 1.4265, 0.86472, 0.66221, 0.56434, 0.34314,
0.18112, 0.07717, 3.995055, 3.0118, 1.824505, 1.397237,
1.190078, 0.723637, 0.381865, 0.162771)),
.Names = c("Concentration", "drug", "rate"),
row.names = c(NA, -16L),
class = "data.frame")
# could use e.g. Km = min(df1$Concentration) for start
# but here we use arbitrary values
ggplot(df1, aes(Concentration, rate)) +
geom_point() +
geom_smooth(method = "nls",
method.args = list(formula = y ~ Vmax * x / (Km + x),
start = list(Km = 50, Vmax = 2)),
data = df1,
se = FALSE,
aes(color = factor(drug)))