# R: Fit regression to asymptotic data

I'm trying to fit a regression to data with a decreasing exponential shape, i.e.:

I have two data sets which I know should conform to this shape, shown in blue and green below:

So, I'd like to fit a curve with an asymptote to these data. Here's a simple quadratic fit:

As you can see, there is an upward inflection at the end of the graph. I know that this means R thinks it can make a better fit of the data this way, but due to the nature of my data (which I know should asymptote at the end), I need to fit a model which is constrained to finish with an asymptote.

Is there a specific way to constrain the regression to fit in this way? You can use the code below to import the green dataset as shown above:

data <- structure(list(x = c(0.1, 0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5,
1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5, 0.1,
0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5,
1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5, 0.1,
0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5,
1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5), y = c(0.9,
0.8, 0.7, 0.8, 0.7, 0.8, 0.7, 0.58, 0.6, 0.5, 0.6, 0.6, 1.48,
1.4, 1.3, 1.3, 1.38, 1.2, 0.1, 0.18, 0.08, 0.18, -2.7756e-17,
0.18, 1.28, 1.3, 1.1, 1.1, 1.1, 1.1, 0.58, 0.58, 0.38, 0.5, 0.48,
0.38, 0.78, 0.68, 0.78, 0.58, 0.5, 0.8, 0.78, 0.48, 0.5, 0.58,
0.6, 0.48, 0.6, 0.5, 0.6, 0.5, 0.6, 0.5, 0.38, 0.38, 0.28, 0.3,
0.18, 0.2, 0.1, 0.08, 0.18, 0.08, 0.2, 0.1, 0.28, 0.2, 0.3, 0.1,
0.2, 0.18, 0.6, 0.4, 0.6, 0.5, 0.4, 0.38, 0.5, 0.48, 0.4, 0.48,
0.4, 0.4)), class = "data.frame", row.names = c(NA, -84L))


Note that I've also tried a log transformation but this still includes the upward inflection at the end, so I think I need a method that constrains the shape.

Edit: The first solution posted here took the approach of eliminating the negative value in the dataset above. Note that I am interested here in constraining the shape of the regression, but this should not assume that the asymptote occurs at zero. To illustrate this, below is another example dataset with the same shape, but which asymptotes below zero.

data_new <- structure(list(x = c(0.1, 0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5,
1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5, 0.1,
0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5,
1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5, 0.1,
0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5,
1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5, 0.1, 0.25, 0.5, 1, 3, 5), y = c(-0.02,
-0.02, -0.12, -0.12, -0.12, -0.12, 0, -0.02, -0.2, 0, -0.1, -0.1,
0.1, -0.12, 0.1, -0.02, 0.1, 0.1, -0.02, -0.1, -0.1, -0.1, -0.1,
-0.1, 0.1, -2.7756e-17, 0.08, -2.7756e-17, -0.02, -2.7756e-17,
0.08, -0.02, -0.02, -0.02, -0.02, -0.02, 0.2, 0.2, 0.1, 0.1,
0.1, 0, 0, 0, 0, -0.1, -0.02, -0.1, 0, 0, 0, -0.02, -0.02, -0.02,
0, 0, 0, 0, 0, -0.02, 0, 0.08, -0.02, 0, 0, 0, 0.1, 0.2, 0.1,
0, 0.1, 0.1, 0, 0, 0, 0, 0, 0, -0.12, 0.08, -0.02, -0.02, -0.02,
-0.32)), class = "data.frame", row.names = c(NA, -84L))


The exponential curve model you described can be achieved tranforming x:

x1 = exp(-x)
mod = lm(y~x1)


This method is the most reasonable if you expect errors around the model underlying data to be symmetric, even better if gaussian. On the other hand, StupidWolf's answer is perfect for log-normal errors, that is a skewed distribution often encountered in strictly positive target variables.

Writing this as something like an extended comment, first of all, one of your y values is negative,

data[data\$y<=0,]
x           y
23 3 -2.7756e-17


You need to sort this out, because you know how this negative number come about when you expect a exponential fit. So we set it to some very small number of the minimum of your positive y:

mV = min(data$$y[data$$y>0])
data$$y[data$$y <= 0] = mV


Then we fit:

fit = lm(log(y) ~ x,data=data)


This is not going to bounce up:

coefficients(fit)
(Intercept)           x
-0.76555216 -0.02818562


And plot:

plot(data)
lines(seq(0,5,by=0.2),exp(predict(fit,data.frame(x=seq(0,5,by=0.2)))),col="blue")


The coefficient is extremely small, I guess from the spread of your data, and you don't see y-values going to zero..

• that negative near-zero value is very odd for sure, but it's possible to fit the same model with gaussian errors over positive and negative values alike. that would be more similar to op's quadratic try. May 13, 2020 at 23:23
• Thanks for this. However, I don't think removing negative or near-zero values is a valid solution here. It is entirely possible that the dataset could asymptote below zero. I'll post an update above with another example dataset to illustrate this. May 14, 2020 at 9:51