强制nls拟合通过指定点的曲线 [英] Forcing nls to fit a curve passing through a specified point
问题描述
我正在尝试将Boltzmann乙状结肠 1 /(1 + exp((x-p1)/ p2))
拟合到这个小型实验数据集:
I'm trying to fit a Boltzmann sigmoid 1/(1+exp((x-p1)/p2))
to this small experimental dataset:
xdata <- c(-60,-50,-40,-30,-20,-10,-0,10)
ydata <- c(0.04, 0.09, 0.38, 0.63, 0.79, 1, 0.83, 0.56)
我知道这很简单。例如,使用 nls
:
I know that it is pretty simple to do it. For example, using nls
:
fit <-nls(ydata ~ 1/(1+exp((xdata-p1)/p2)),start=list(p1=mean(xdata),p2=-5))
我得到以下结果:
Formula: ydata ~ 1/(1 + exp((xdata - p1)/p2))
Parameters:
Estimate Std. Error t value Pr(>|t|)
p1 -33.671 4.755 -7.081 0.000398 ***
p2 -10.336 4.312 -2.397 0.053490 .
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.1904 on 6 degrees of freedom
Number of iterations to convergence: 13
Achieved convergence tolerance: 7.079e-06
但是,由于理论原因,我需要(因为理论原因),拟合曲线才能精确地通过点(-70,0)
。尽管上面显示的拟合表达式的值在 x = -70
时接近零,但它不完全是零,这不是我想要的。
However, I need (due to theoretical reasons) the fitted curve to pass precisely through the point (-70, 0)
. Although the value of the fitted expression showed above passes near zero at x = -70
, it is not exactly zero, which is not what I want.
所以,问题是:有没有办法告诉 nls
(或其他函数)来适应相同的表达式,但是强制它通过指定的点?
So, the question is: Is there a way to tell nls
(or some other function) to fit the same expression but forcing it to pass through a specified point?
更新:
如前所述在注释中,使用我提供的函数(Boltzmann乙状结肠)强迫拟合通过点(-70,0)在数学上是不可能的。另一方面,@ Cleb和@BenBolker解释了如何强制拟合通过任何其他点,例如(-50,0.09)。
As it has been mentioned in the comments, it is mathematically impossible to force the fit to go through the point (-70,0) using the function I provided (the Boltzmann sigmoid). On the other hand, @Cleb and @BenBolker have explained how to force the fit to go through any other point, for instance (-50, 0.09).
推荐答案
以@Cleb的答案为基础,这是一种选择函数必须经过的指定点并求解方程的结果的方法参数之一:
Building on @Cleb's answer, here's a way to pick a specified point the function must pass through and solve the resulting equation for one of the parameters:
dd <- data.frame(x=c(-60,-50,-40,-30,-20,-10,-0,10),
y=c(0.04, 0.09, 0.38, 0.63, 0.79, 1, 0.83, 0.56))
初始拟合(使用 plogis()
而不是 1 /(1 + exp(-...))
为方便起见):
Initial fit (using plogis()
rather than 1/(1+exp(-...))
for convenience):
fit <- nls(y ~ plogis(-(x-p1)/p2),
data=dd,
start=list(p1=mean(dd$x),p2=-5))
现在插入(x3,y3)
并求解p2:
Now plug in (x3,y3)
and solve for p2:
y3 = 1/(1+exp((x-p1)/p2))
logit(x) = qlogis(-x) = log(x/(1-x))
e.g. plogis(2)=0.88 -> qlogis(0.88)=2
qlogis(y3) = -(x-p1)/p2
p2 = -(x3-p1)/qlogis(y3)
设置一个函数并将其插入 p2
:
Set up a function and plug it in for p2
:
p2 <- function(p1,x,y) {
-(x-p1)/qlogis(y)
}
fit2 <- nls(y ~ plogis(-(x-p1)/p2(p1,dd$x[3],dd$y[3])),
data=dd,
start=list(p1=mean(dd$x)))
绘制结果:
plot(y~x,data=dd,ylim=c(0,1.1))
xr <- data.frame(x = seq(min(dd$x),max(dd$x),len=200))
lines(xr$x,predict(fit,newdata=xr))
lines(xr$x,predict(fit2,newdata=xr),col=2)
这篇关于强制nls拟合通过指定点的曲线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!