如何使用非线性函数拟合数据并使用ggplot()绘制数据和拟合结果

5

一项测量显示出一个类似于平方根函数带有偏移和系数的信号。我该如何找到系数并在同一张图中绘制原始数据和拟合曲线?

require(ggplot2)
require(nlmrt)  # may be this will help later..?

# generate simulated measurement data

time <- seq(-10,20,0.2)

signal <- sqrt(time + 2) # generate sqrt signal; includes some NA
signal[is.na(signal)] <- 0 # set all NA to zero
signal <- signal + rnorm(length(time)) * 0.1  # add noise

df <- data.frame(x=time, y=signal)

# find coefficiants for y ~ b * sqrt(x - a)
# no idea how...

# plot raw data and fitted curve in one ggplot diagram

ggplot()+
    geom_point(data=df, aes(x=x, y=y))

enter image description here


1
只是一个提示,你可能想要使用 y ~ b * sqrt(x - a),而不是 a + b*sqrt(c*x) - Hong Ooi
1
如果您无法事先指定截止点(即,如果它是一个拟合参数),那么您可能需要单独进行拟合(它不适合线性模型框架,并且由于适合截止点的拟合优度在数据点之间的区间上是平坦的,因此存在特别棘手的方面)。如果您可以指定截止点,那么我认为您可以构造一个虚拟变量并执行此操作... - Ben Bolker
作为第一步,我可以手动定义一个截止常量。稍后我想自动找到它。但这可能是另一个问题的主题。 - Jonas Stein
1个回答

5
只要您知道截断点在哪里,并且截断点之前的值为零:
sfun <- function(x,brk,a=1) {
    ifelse(x<brk,0,suppressWarnings(a*sqrt(x-brk)))
}

(suppressWarnings() 的作用是因为 ifelse 会对所有的 x 值同时评估 ifelse 情况,我们不想看到关于负数求平方根的警告)

测试(未显示):

curve(sfun(x,1,1),from=0,to=10) ## test (not shown)

模拟一些数据:

x <- seq(0,10,length=101)
set.seed(1)
y <- rnorm(length(x),sfun(x,1,1),sd=0.25)
DF <- data.frame(x,y)

因为我们只需要确定平方根函数的缩放方式,所以可以通过原点回归来实现这一点(如果想允许截断点以下的值为非零,则去掉 -1):

library("ggplot2")
theme_set(theme_bw())
ggplot(DF,aes(x,y))+geom_point()+
    geom_smooth(method="lm",
                formula=y~sfun(x,brk=1)-1)
ggsave("truncsqrt.png")

enter image description here


哎呀,我甚至没有注意到你已经提供了自己的模拟代码。任何想要的人都可以随意编辑原帖中的示例。 - Ben Bolker
太好了!灰色带的宽度是如何定义的?我能否将系数作为数字获取? - Jonas Stein
1
灰色带是95%置信区间。如果您想要系数,只需执行lm(y~sfun(x,brk=1)-1,data=DF) - Ben Bolker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接