# Compare non-linear model parameter estimates between conditions

What is the appropriate way to test for significant differences between the same parameter estimate from 2 nonlinear models? An example using R - here are 2 datasets:

library(tidyverse)
#example from ?nls
DNase1 <- subset(DNase, Run == 1)
DNase2 <- subset(DNase, Run == 2)


Both datasets can be fit with a nonlinear function using the nls() function and coefficients extracted:

   ## fit models and extract coefficients
m1 <- nls(density ~ SSlogis(log(conc), Asym, xmid, scal), DNase1)
m1_coef <- tidy(m1) %>%
mutate(Run = 1)

m2 <- nls(density ~ SSlogis(log(conc), Asym, xmid, scal), DNase2)
m2_coef <- tidy(m2) %>%
mutate(Run = 2)

pars <- rbind(m1_coef, m2_coef) %>%
dplyr::filter(term == "Asym")

print(pars)


For simplicity, some of the results include 2 estimates of the 'Asym' parameter, one estimate for each condition (Run 1 & 2) made by each of the 2 models:

     term Estimate Std. Error  t value     Pr(>|t|) Run
1    Asym 2.345182  0.0781541 30.00715 2.165539e-13   1
2    Asym 2.595948  0.0646589 40.14835 5.109901e-15   2


Is there a way test if the estimate for 'Asym' from Run 2 (2.345) is significantly different than the estimate from Run 1 (2.596)?

## 2 Answers

Create a model m12 consisting of separate parameters for each run and a model m0 where the parameters are the same for each run and then compare those two models using an F test. In R that would be done like this:

# m1 and m2 will be used to set starting values for m12 and a0
fo <- density ~ SSlogis(log(conc), Asym, xmid, scal)
m1 <- nls(fo, DNase, subset = Run == 1)
m2 <- nls(fo, DNase, subset = Run == 2)

Logis <- function(x, Asym, xmid, scal) Asym / (1 + exp((xmid - x)/ scal))

# Run 1 and Run 2 each have a separate set of parameters.
# (Run is a factor whose labels don't correspond to its levels so make it numeric.)
m12 <- nls(density ~ Logis(log(conc), Asym[Run], xmid[Run], scal[Run]),
transform(DNase, Run = as.numeric(as.character(Run))),
subset = Run %in% 1:2,
start = as.data.frame(rbind(coef(m1), coef(m2))))

# Run 1 and Run 2 have the same set of parameters
m0 <- nls(fo, DNase, subset = Run %in% 1:2)

anova(m0, m12)


giving:

Analysis of Variance Table

Model 1: density ~ SSlogis(log(conc), Asym, xmid, scal)
Model 2: density ~ Logis(log(conc), Asym[Run], xmid[Run], scal[Run])
Res.Df Res.Sum Sq Df   Sum Sq F value    Pr(>F)
1     29   0.096915
2     26   0.008478  3 0.088437  90.408 7.044e-14 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1


If we want to test only whether Asym differs but not whether xmid and scal are the same then create a model a0 where Asym is the same but the other parameters can differ and compare it to m12.

# same Asym for Run 1 and Run 2 but other parameters separate
a0 <- nls(density ~ Logis(log(conc), Asym, xmid[Run], scal[Run]),
transform(DNase, Run = as.numeric(as.character(Run))),
subset = Run %in% 1:2,
start = c(Asym = (coef(m1)[] + coef(m2)[])/2,
as.data.frame(rbind(coef(m1)[-1], coef(m2)[-1]))))

anova(a0, m12)


giving:

Analysis of Variance Table

Model 1: density ~ Logis(log(conc), Asym, xmid[Run], scal[Run])
Model 2: density ~ Logis(log(conc), Asym[Run], xmid[Run], scal[Run])
Res.Df Res.Sum Sq Df    Sum Sq F value  Pr(>F)
1     27  0.0103246
2     26  0.0084778  1 0.0018468  5.6639 0.02494 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1


After further investigation it seems that in some cases constructing 95% CI around the estimate using the Std.Error of the Estimate can serve as a significance test (I observed this approach in some biology research papers). Furthermore, the approach described in Ch. 8 from the book Nonlinear Regression R provides useful means of "Comparison of Specific Parameters" as described in detail in section 8.2.2. This reference contains highly detailed walkthrough of this procedure. In short, datasets can be combined into one dataframe that includes columns for the predictor, response, and group IDs. Then the model fit using nls() with a grouping variable on the parameters assumed to be different between groups and an F-test (via anova()) can be used to compare models/test the null hypothesis that a parameter between groups are equal.