It looks like you're plotting the opening of a valve over time. As the valve opens, the temperature of something (a fluid in the valve?) increases.
Given that you data follows an s-curve with two bends, I would model the process using a third-order polynomial.
mydata <- data.frame(valve = seq(from = 5, to = 100, by = 5),
temp = c(rep(75, 4), 76, 79, 83, 91, 98, 103, 107, 110, 112, 113, rep(114, 3), rep(115, 3)))
lm <- lm(temp ~ poly(valve,3), data=mydata)
poly3 <- predict(lm, newdata=data.frame(mydata$valve))
plot(mydata)
points(as.data.frame(cbind(mydata$valve,poly3)), pch=4, col='blue')
legend(5, 110, legend=c("Data", "3rd order Polynomial"),
pch=c(1,4), col=c('black', 'blue'), cex=0.8)
Graph of results below.
Alternatively, you can get a better fit with a spline regression. A spline is a smooth function built out of smaller, component functions.
library(splines)
mydata <- data.frame(valve = seq(from = 5, to = 100, by = 5),
temp = c(rep(75, 4), 76, 79, 83, 91, 98, 103,
107, 110, 112, 113, rep(114, 3), rep(115, 3)))
knots_x <- quantile(mydata$valve, probs=c(0.25, .5, 0.75)) #setting knots at default IQR
bounds_x <- c(20, 80) #assuming no change in temp before valve is 20% open and after 80% closed
lm2 <- lm(temp ~ ns(mydata$valve, knots=knots_x, Boundary.knots = bounds_x), data = mydata)
spline <- predict(lm2, newdata=data.frame(mydata$valve))
plot(mydata)
points(as.data.frame(cbind(mydata$valve,spline)), pch=4, col='blue')
legend(5, 110, legend=c("Data", "Spline Predictions"),
pch=c(1,4), col=c('black', 'blue'), cex=0.8)
By limiting the boundary for the knots within the interval that the valve openness affects the temperature, I basically eliminated the over-shooting of the previous polynomial model. Then I put in the knots in the IQR for the data (not adjusted for the bounds).
Note that the model can still extrapolate outside of the bounds, but the model fits the data (given the assumptions) much more closely.