【问题标题】:Evaluating asymptote in R nls for multiple factors评估 R nls 中多个因素的渐近线
【发布时间】:2016-12-24 23:25:12
【问题描述】:

我正在尝试使用 NLS 在 R 中评估不同人群是否达到不同的渐近线。这里我有两个 data.frames df1 只有一个人群(由站点表示)

df1<- structure(list(Site = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("ALT01", 
"ALT02", "ALT03", "Cotton", "Deep", "Eckhardt", "Green", "Johnson", 
"Kissinger", "Marsh", "Sand", "Shypoke", "Sora", "Spike", "Tamora", 
"WRP01", "WRP05", "WRP08", "WRP10", "WRP11", "WRP12", "WRP14", 
"WRP15", "WRP18"), class = "factor"), Nets = 1:18, Cumulative.spp = c(12L, 
13L, 15L, 17L, 17L, 17L, 17L, 19L, 19L, 19L, 19L, 20L, 22L, 22L, 
22L, 22L, 22L, 22L)), .Names = c("Site", "Nets", "Cumulative.spp"
), row.names = c(NA, 18L), class = "data.frame")

而 df2 必须有种群(再次由 Site 表示)

df2 <- structure(list(Site = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("ALT01", 
"ALT02", "ALT03", "Cotton", "Deep", "Eckhardt", "Green", "Johnson", 
"Kissinger", "Marsh", "Sand", "Shypoke", "Sora", "Spike", "Tamora", 
"WRP01", "WRP05", "WRP08", "WRP10", "WRP11", "WRP12", "WRP14", 
"WRP15", "WRP18"), class = "factor"), Nets = c(1L, 2L, 3L, 4L, 
5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 
1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 
15L, 16L, 17L, 18L), Cumulative.spp = c(12L, 13L, 15L, 17L, 17L, 
17L, 17L, 19L, 19L, 19L, 19L, 20L, 22L, 22L, 22L, 22L, 22L, 22L, 
7L, 10L, 11L, 12L, 13L, 14L, 14L, 14L, 15L, 15L, 16L, 16L, 16L, 
16L, 16L, 17L, 17L, 17L)), .Names = c("Site", "Nets", "Cumulative.spp"
), row.names = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 
12L, 13L, 14L, 15L, 16L, 17L, 18L, 25L, 26L, 27L, 28L, 29L, 30L, 
31L, 32L, 33L, 34L, 35L, 36L, 37L, 38L, 39L, 40L, 41L, 42L), class = "data.frame")

当我为一个人群建模时,一切看起来都很棒:

Model1<-nls(Cumulative.spp ~ SSasympOff(Nets, A, lrc, c0), data = df1)

我正在尝试做的是看看我是否可以将多个群体添加到同一个模型并添加一个站点变量,我已经尝试过:

Model2<-nls(Cumulative.spp ~ SSasympOff(Nets, A, lrc, c0) + Site , data = df2)

还有这个:

Model2<-nls(Cumulative.spp ~ SSasympOff(Nets + Site , A, lrc, c0), data = df2)

但到目前为止没有运气,任何帮助将不胜感激。

【问题讨论】:

  • 查看nlme::gnls(),尤其是params 参数...
  • 谢谢@BenBolker 我试图理解params 的文档,虽然它说每个参数都有不同的模型我还没有找到任何关于如何要做到这一点,你能帮我多一点吗?
  • 类似于gnls(Cumulative.spp ~ SSasympOff(Nets, A, lrc, c0), params = Nets ~ Site, data = df2)(如果您希望Nets 的效果在不同站点之间有所不同)或params = Nets+A+lrc+c0~Site 如果您希望所有参数都不同(尽管在这种情况下您可以细分数据并分别拟合每个站点;唯一的(?)差异将是残差方差的汇总与站点特定估计)
  • 感谢@BenBolker,因为您看到有人提出了使用 nls 的解决方案,但我仍然想学习 gnls 方式,我尝试了 gnls(Cumulative.spp ~ SSasympOff(Nets, A, lrc, c0), params = Nets ~ Site, data = df2) 并给了我这个错误:错误在 eval(expr, envir, enclos) 中:找不到对象'A'; gnls(Cumulative.spp ~ SSasympOff(Nets, A, lrc, c0), params = Nets+A+lrc+c0~Site, data = df2) 给了我另一个错误,这个:gnls(Cumulative.spp ~ SSasympOff(Nets, A, lrc, c0), data = df2) 仍然有效

标签: r nls


【解决方案1】:

我们假设您希望为两个总体设置不同的 Asym 参数,但要使用通用的 lrcc0 参数。

首先在(1)中我们展示了如何修改问题中的解决方案以获得答案。 (1) 中的大部分代码只是为了获取起始值,但实际拟合只有一行代码——如果你算上我们在单独的一行中定义了公式的事实,那就是两行。

然后在 (2) 中,我们展示了如何通过使用算法 "plinear" 来简化 (1),从而无需获取线性参数的起始值。在(2a)中,我们展示了更容易扩展到更多站点的进一步简化,在(2b)中,我们在所有站点都存在的情况下进一步简化(问题中不是这种情况,但可能是实际情况)数据)。

1) 默认算法 我们可以通过分别拟合每个总体(fm1fm2)和一起拟合(fm3)来获得nls 中的起始值。最后用不同的Asym参数(fm4)拟合模型。

# get starting values
fo <- Cumulative.spp ~ SSasympOff(Nets, A, lrc, c0)
fm1 <- nls(fo, df2, subset = Site == "ALT01")
fm2 <- nls(fo, df2, subset = Site == "ALT03")
fm3 <- nls(fo, df2)
st <- c(A1 = coef(fm1)[["A"]], A2 = coef(fm2)[["A"]], coef(fm3)[c("lrc", "c0")])

# fit    
fo4 <- Cumulative.spp ~ SSasympOff(Nets, A1*(Site=="ALT01")+A2*(Site=="ALT03"), lrc, c0)
fm4 <- nls(fo4, data = df2,  start = st)

plot(Cumulative.spp ~ Nets, df2, col = Site)
points(fitted(fm4) ~ Nets, df2, col = "red", pch = 20)

2) plinear 实际上Asym 是特殊的,因为模型在其中是线性的,我们可以使用它来简化上述内容,因为如果我们切换,我们不需要线性参数的起始值到algorithm="plinear"。这消除了运行fm1fm2 的需要。我们只需要fm3 来生成起始值。请注意,"plinear" 要求公式的 RHS 是一个矩阵,每列乘以一个线性参数的系数。这里我们有两个线性参数(每个SiteAsym)所以它是一个两列矩阵。

# get starting values
fo <- Cumulative.spp ~ SSasympOff(Nets, A, lrc, c0)
fm3 <- nls(fo, df2)    
st5 <- coef(fm3)[c("lrc", "c0")]

# fit
mm <- with(df2, cbind(Site=="ALT01", Site=="ALT03"))
fo5 <- Cumulative.spp ~  mm * SSasympOff(Nets,1,lrc,c0)
fm5 <- nls(fo5, data = df2,  start = st5, algorithm = "plinear")

2a) mm 也可以这样写,其优点是可以扩展到更多站点:

mm <- model.matrix(~ Site - 1, transform(df2, Site = droplevels(Site)))

2b) 如果Site 因子的所有级别都在数据中表示,那么我们可以进一步简化为droplevels(Site)(它会删除未使用的级别)然后可以简单地为Site允许我们写:

mm <- model.matrix(~ Site - 1, df2)

更新:一些修复和改进。

【讨论】:

  • 效果很好,谢谢。如果不是太大问题,你能不能把第一部分删掉,我觉得用mm &lt;- model.matrix(~ Site - 1, transform(df2, Site = droplevels(Site))) fo5 &lt;- Cumulative.spp ~ mm * SSasympOff(Nets, 1, lrc, c0)和thenfm5 &lt;- nls(fo5, data = df2, start = st5, algorithm = "plinear")就可以了,第一部分可能会让人迷惑,谢谢
  • 我添加了标题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-08
  • 2019-04-24
  • 2021-07-07
  • 2015-03-22
  • 2018-04-22
  • 1970-01-01
  • 2013-07-17
相关资源
最近更新 更多