Reputation: 862
How to smoothen the fit curve?
XY <- data.frame(cbind(Values = c(91.8, 95.3, 99.8, 123.3, 202.9, 619.8, 1214.2, 1519.1, 1509.2, 1523.3, 1595.2, 1625.1),
Concn = c(1000, 300, 100, 30, 10, 3, 1, 0.3, 0.1, 0.03, 0.01, 0)))
nls.fit <- nls(Values ~ (ymax* Concn / (ec50 + Concn)) + Ns*XY$Concn + ymin, data=XY,
start=list(ymax=max(XY$Values), ymin = min(XY$Values), ec50 = 3, Ns = 0.2045514))
plot(XY$Values ~ XY$Concn , data = XY, col = 4, main = "XY Std curve", log = "x")
lines(XY$Concn, predict(nls.fit))
When I tried the following script, I get error msg.
SmoothX <- seq(min(XY$Values), max(XY$Values), length = 100)
lines(SmoothX, predict(nls.fit,SmoothX), col='red', lwd=2)
Error in (function (formula, data = NULL, subset = NULL, na.action = na.fail, : variable lengths differ (found for 'SmoothX')
How to fix the error?
Upvotes: 2
Views: 287
Reputation: 269421
First make sure that XY is sorted in ascending order of Concn
to ensure that when we use lines
that each point is connected to the next sorted point and not to some other point. Also be sure to remove XY
from the formula since it is already specified in the data
argument and will cause problems if present. Use the plot
and lines
argument, subset
, to exclude 0 from the data used in plot
and lines
since they specify logarithmic scales.
o <- order(XY$Concn)
XY <- XY[o, ]
fo <- Values ~ (ymax* Concn / (ec50 + Concn)) + Ns * Concn + ymin
st <- list(ymax=max(XY$Values), ymin = min(XY$Values), ec50 = 3, Ns = 0.2045514)
nls.fit <- nls(fo, data = XY, start = st)
plot(Values ~ Concn, XY, subset = Concn > 0, col = 4, log = "x")
title(main = "XY Std curve")
lines(predict(nls.fit, new = list(Concn = Concn)) ~ Concn, XY, subset = Concn > 0) ##
Optionally, it could be made even smoother by replacing the lines
statement (marked ## above) with the following 3 lines of code to provide a greater number of points equally spaced on a log scale. Note that we remove the 0 point before taking logarithms.
logRange <- with(XY, log(range(Concn[Concn > 0])))
x <- exp(seq(logRange[1], logRange[2], length = 100))
lines(x, predict(nls.fit, new = list(Concn = x)))
Omitting the line marked ## and then running all the rest of the code above including the last 3 lines we get:
Upvotes: 2
Reputation: 226057
First of all, you need to use a formula in nls()
without XY$
in it:
nls.fit <- nls(Values ~ (ymax* Concn / (ec50 + Concn)) +
Ns*Concn + ymin,
data=XY,
start=list(ymax=max(XY$Values), ymin = min(XY$Values),
ec50 = 3, Ns = 0.2045514))
Plot:
plot(Values ~ Concn , data = XY, col = 4, main = "XY Std curve",
log = "x")
If you're going to plot on a log-X scale it will help to spread your prediction values evenly on the log scale. You also need the prediction data to be a data frame with the same variable name (Conc
) as the predictor variable in your model:
SmoothX <- with(XY,
data.frame(Concn=10^seq(min(log10(Concn[Concn>0])),
max(log10(Concn)), length = 100)))
pp <- predict(nls.fit,SmoothX)
lines(SmoothX$Concn, pp, col='red', lwd=2)
plot(Values ~ Concn , data = XY, col = 4, main = "XY Std curve",
log = "x")
SmoothX <- with(XY,
data.frame(Concn=10^seq(min(log10(Concn[Concn>0])),
max(log10(Concn)), length = 100)))
pp <- predict(nls.fit,SmoothX)
lines(SmoothX$Concn, pp, col='red', lwd=2)
Upvotes: 1
Reputation: 335
First I think your new data to be used in the predictions should be using concentrations instead of values:
SmoothX <- seq(min(XY$Concn), max(XY$Concn), length = 100)
Additionally, look that SmoothX and predict(nls.fit,SmoothX) differ in length:
str(SmoothX)
num [1:100] 91.8 107.3 122.8 138.3 153.8 ...
str(predict(nls.fit,SmoothX))
num [1:12] 109.5 49 52.3 120.6 298.6 ...
But, if you include list(Concn=SmoothX)
you will get a vector of 100 values as your new data vector length is.
str(predict(nls.fit,list(Concn=SmoothX)))
num [1:100] 1714 324.7 175.5 119.6 91.8 ...
This works better but it still gives a warning message and a poorly ugly red line :c.
lines(SmoothX, predict(nls.fit,list(Concn=SmoothX)), col='red', lwd=2)
Warning message: In (ymax * Concn/(ec50 + Concn)) + Ns * XY$Concn : longer object length is not a multiple of shorter object length
Upvotes: 1