# What is a good starting model for fitting a rotated sigmoidal curve?

I'm trying to make a model to fit a rotated sigmoidal curve in R but don't know where to start when looking for an appropriate equation for the model.

Some example data and the type of fit I'm getting at the moment are shown below:

library(tidyverse)
#example data
df <- data.frame(x = c(50, 54, 56, 55, 58, 64, 91, 148, 345, 722,
1641, 4320, 4931, 5224),
y = c(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
2048, 4096, 8192))

# 4th order polynomial fitting
model1 <- lm(y ~ poly(x,4, raw = TRUE), data = df)
# inverse log non-linear model?
model2 <- nls(y ~ I(1 / x * a) + b * x, data = df,
start = list(a = 1, b = 1))

# make some evenly spaced points for x and fit models
model_df <- data.frame(logx = seq(1.7, 3.7, by=0.01)) %>%
mutate(x = 10^logx)
model_df$$fit1 <- predict(model1, model_df) model_df$$fit2 <- predict(model2, model_df)

# plot on log axes
ggplot(df) +
aes(x = x, y = y) +
geom_point(size = 4) +
geom_point(data = model_df, aes(x = x, y = fit1), colour = "red",
size = 1) +
geom_point(data = model_df, aes(x = x, y = fit2), colour = "blue",
size = 1) +
scale_x_log10() +
scale_y_log10()

Does anyone know any suitable way to fit a curve like this?

• What do you want to do with the model? A GAM smoother would be easiest. A segmented linear model could be sufficient. I'm not a huge fan of selecting an arbitrary non-linear function without deriving it from the data-generating process based on appropriate scientific theory. Commented Jun 14 at 9:23
• I would like to use the model to estimate y (sample concentration) from x (assay signal). The points given represent a standard curve of known concentration samples
– jaysmith
Commented Jun 14 at 11:50
• Do you know why the values jump up suddenly above x=3300? I would consider simply saying that the assay fails at that point and fit a simple model to the rest of it. Commented Jun 14 at 21:30
• could you add all your descriptions to the main question. so are you saying, x is also a concentration and ideally y=x? Commented Jun 16 at 7:03

Here is one solution with natural splines implemented with splines::ns.

I guess the correct solution depends on what you want to do with the model. Another option is interpolating splines. splinefun is a useful function for generating interpolating spline function that is differentiable.

library(tidyverse)
library(splines)

df <- data.frame(
x = c(50,54,56,55,58,64,91,148,345,722,1641,4320,4931,5224),
y = c(1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192)
)

spline_obj <- ns(df$x, df = 6) df <- df |> bind_cols(predict(spline_obj, df$x))

model <- lm(y ~ ., data = df |> select(-x))

df$pred <- predict(model, df) df2 <- tibble( x = seq(min(df$$x), max(df$$x), length.out = 200) ) df2 <- df2 |> bind_cols(predict(spline_obj, df2$x))

df2$pred <- predict(model, df2) print( ggplot() + geom_point(aes(x, y), data = df) + geom_line(aes(x, pred), data = df2) ) Created on 2024-06-14 with reprex v2.1.0 Note : In order to use an available software the symbols in the answer below are not the same symbols that in the question. Note: It should be better to chose an equation model coming from the modelisation of the phenomenon involved in the experiment from which the data is coming. Since it is asked to find an equation model many variant equations can be proposed. The drawback is that the chosen equation probably will have no physical signifiance even if the fitting is good on purely mathematical viewpoint. FIRST PART : INSPECTION The data points are drawn with various scales (linear, logaritmic). The shape the best looking to a logistic curve appears on Figure 4. Therefore the logistic model is chosen for the calculus below. SECOND PART : Logistic regression. For example a non iterative method which doesn't need initial "guessed" values of parameters is used : Result of logistic regression : THIRD PART : Inversion of the equation. For more accuracy of fitting one have to use a software for non-linear regression. The values of the parameters found above can be good "guessed" values to start the iterative process. General information about the above method of regression : https://fr.scribd.com/doc/14674814/Regressions-et-equations-integrales Thank you for the answers - the inverse of the logistic model looked like the appropriate starter equation; however my R knowledge is not enough to be able to turn that into a working model. The suggestion to use GAM was very helpful - this gave a very neat fit to these example points. Adding to the code in the question: model9 <- gam(y ~ s(x, bs = "tp"), data = df) # this works if points are averaged model_df$fit9 <- predict(model9, model_df)

ggplot(df) +
aes(x = x, y = y) +
geom_point(size = 4) +
geom_point(data = model_df, aes(x = x, y = fit1), colour = "red", size = 1) +
geom_point(data = model_df, aes(x = x, y = fit2), colour = "blue", size = 1) +
geom_point(data = model_df, aes(x = x, y = fit9), colour = "green4", size = 1) +
scale_x_log10() +
scale_y_log10()

gives the fit in green below

This will work nicely for fitting a standard curve of points with known concentration in an ELISA experiment where x is the assay signal, and we need to determine y (concentration) for unknown samples.