我试图评估不同的人群是否使用NLS在R中达到不同的渐近线。这里我有两个数据。帧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必须与人口(再次由网站代表)
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)
但到目前为止没有运气,任何帮助都会受到赞赏。
答案 0 :(得分:2)
我们假设您希望为两个群体提供不同的Asym
参数,但需要使用常见的lrc
和c0
参数。
首先在(1)中我们展示如何修改问题中的解决方案以获得答案。 (1)中的大多数代码只是为了得到起始值,但实际拟合只是一行代码 - 如果你计算我们在一个单独的行中定义公式的事实,则为两行。
然后在(2)中,我们展示了如何通过使用算法"plinear"
来简化(1),从而无需获得线性参数的起始值。在(2a)中,我们展示了一个更容易扩展到更多站点的进一步简化,并且在(2b)中我们在所有站点都存在的情况下进一步简化(在问题中不是这种情况,但在实际情况中可能是这种情况)数据)。
1)默认算法我们可以通过单独拟合每个群体(nls
,fm1
)和fm2
来获取fm3
中的起始值})。最后,使用不同的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"
。这样就无需运行fm1
和fm2
。我们只需要fm3
来生成起始值。请注意,"plinear"
要求公式的RHS为矩阵,每列乘以一个线性参数的系数。这里我们有两个线性参数(每个Asym
Site
),因此它是一个双列矩阵。
# 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)
更新:一些修复和改进。