【问题标题】:How to apply a nonlinear regression within a data subset from a long data frame?如何在长数据帧的数据子集中应用非线性回归?
【发布时间】:2020-05-14 16:46:17
【问题描述】:

我有一个数据框,其中包含来自不同实验的多个结果。我想将每个实验的数据分别拟合到一个特定的函数,但是,我的 R 知识很浅。有什么帮助吗?

在下面的MWE中,参数的起始值为ex1数据

ex <- c(rep("ex1", times=4), rep("ex2", times=4))
x <- rep(c(0,60,120,240), times = 2)
y <- c(0,3.73,3.08,4.07,0,1.4,2.6,2.6)

df <- data.frame(ex, x, y)

m <- nls(formula = y ~ ((a^2)*b*x)/(1+(a*b*x)),
         data = df,
         start = list(a=4.071, b=0.0253))

起始值:

对于 ex1:a = 4.071b = 0.0253

对于 ex2:a = 2.584b = 0.0155

【问题讨论】:

  • 我不确定这是可重现的(奇异梯度)。但是,我相信您尝试做的事情可以通过split 然后lapply 来完成。例如,使用简单的线性模型:list_of_experiments &lt;- split(df, ex) 然后lapply(list_of_experiments, function(df) lm(y ~ x, data = df))
  • @JasonAizkalns 非常抱歉,我发布了错误的数据框。我编辑了原始帖子。单独地,ex1 和 ex2 运行没有问题,但是当我使用你的技巧时,我得到了奇异的渐变。我需要更改每个实验的起始值

标签: r dataframe subset non-linear-regression nls


【解决方案1】:

1) 一个使用分组的 nls 可以像这样在一个 nls 调用中完成:

fo <- y ~ ((a[ex]^2)*b[ex]*x)/(1+(a[ex]*b[ex]*x))
st <- list(a = c(4.071, 2.504), b = c(0.0253, 0.0155))

m <- nls(fo, df, start = st)
m

给予:

Nonlinear regression model
  model: y ~ ((a[ex]^2) * b[ex] * x)/(1 + (a[ex] * b[ex] * x))
   data: df
     a1      a2      b1      b2 
3.76849 3.58989 0.06521 0.00385 
 residual sum-of-squares: 0.6989

Number of iterations to convergence: 8 
Achieved convergence tolerance: 4.731e-06

2) 映射 或者我们可以遍历对每个组执行单独的 nls 的组。 st 来自上方。

fo1 <- y ~ ((a^2)*b*x)/(1+(a*b*x))
st1 <- split(as.data.frame(st), levels(df$ex))

L <- Map(nls, data = split(df, df$ex), st1, MoreArgs = list(formula = fo1))
L

给出nls 对象的列表:

$ex1
Nonlinear regression model
  model: y ~ ((a^2) * b * x)/(1 + (a * b * x))
   data: dots[[1L]][[2L]]
      a       b 
3.76848 0.06521 
 residual sum-of-squares: 0.4922

Number of iterations to convergence: 7 
Achieved convergence tolerance: 3.774e-06

$ex2
Nonlinear regression model
  model: y ~ ((a^2) * b * x)/(1 + (a * b * x))
   data: dots[[1L]][[2L]]
      a       b 
3.58989 0.00385 
 residual sum-of-squares: 0.2067

Number of iterations to convergence: 9 
Achieved convergence tolerance: 3.302e-06

3) 更新 第三种方法是首先运行组合的 nls,然后为每个组设置子集。 fo1st 来自上方。

m2 <- nls(fo1, df, start = sapply(st, mean))
lvs <- levels(df$ex)
L2 <- lapply(lvs, function(lv) do.call("update", list(m2, subset = df$ex == lv)))

它还给出了nls 对象的列表。

4) nlsList 另一种方法是使用 nlme 包中的 nlsList。 st 来自上方。

library(nlme)

fo2 <- y ~ ((a^2) * b * x)/(1 + (a * b * x)) | ex
m3 <- nlsList(fo2, df, start = sapply(st, mean))
m3

给出以下nlsList 对象:

Call:
  Model: y ~ ((a^2) * b * x)/(1 + (a * b * x)) | ex 
   Data: df 

Coefficients:
           a           b
ex1 3.768487 0.065212898
ex2 3.589892 0.003850294

Degrees of freedom: 8 total; 4 residual
Residual standard error: 0.4179985

残差平方和

对于(1),残差平方和为

tapply(resid(m)^2, df$ex, sum)

对于 (2) 它是:

sapply(L, deviance)

and for (3) and (4) 用 L2 或 m3 代替 L.

【讨论】:

  • 谢谢!!!,有办法单独获取residual sum-of-squares吗?
  • model &lt;- nls(fo, df, start = st) 然后是:sum(model$m$resid() ^ 2)sum(summary(model)$residuals ^ 2)
  • 已在残差平方和的答案中添加了一节。
猜你喜欢
  • 2021-07-04
  • 1970-01-01
  • 2021-01-03
  • 1970-01-01
  • 2021-08-21
  • 2013-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多