我的问题与估算Malthusian growth model中的人口增长率有关。作为玩具示例,请考虑玩具数据集df
:
structure(list(x= c(0L, 24L, 48L, 72L, 96L, 120L, 144L, 168L
), y = c(10000, 18744.0760659189, 35134.0387564953, 65855.509495469,
123440.067934292, 231377.002294256, 433694.813090781, 812920.856596808
)), .Names = c("x", "y"), row.names = c(NA, -8L), class = "data.frame")
我试图通过指数模型:
来拟合这个数据集y = 10000 * (e^(r * x))
并估算r
。使用非线性回归nls()
:
fit <- nls(y ~ (10000 * exp(r*x)), data=df)
我收到以下错误:
Error in getInitial.default(func, data, mCall = as.list(match.call(func, :
no 'getInitial' method found for "function" objects
我也试过lm()
fit <- lm(log(y) ~ (10000 * exp(r*x)), data=df)
但是
Error in terms.formula(formula, data = data) :
invalid model formula in ExtractVars
我该如何解决这个问题?如何将数据拟合到我所拥有的指数模型?
此外,我是否可以考虑采用其他方法来拟合人口增长模型? glm()
合理吗?
答案 0 :(得分:3)
使用lm()
请阅读?formula
以了解公式的正确说明。现在我假设您已经阅读过,我将继续。
首先,您的模型在对LHS和RHS进行log
转换后变为:
log(y) = log(10000) + r * x
常数是已知值,无法估算。这种常量在offset
中称为lm
。
您应该使用lm
:
# "-1" in the formula will drop intercept
fit <- lm(log(y) ~ x - 1, data = df, offset = rep(log(10000), nrow(df)))
# Call:
# lm(formula = log(y) ~ x - 1, data = df, offset = rep(log(10000), nrow(df)))
# Coefficients:
# x
# 0.02618
正如您所发现的那样,fit
是一个长度为13的列表。请参阅&#34;值&#34; ?lm
的部分,你会更好地了解它们是什么。其中,拟合值为$fitted
,因此您可以通过以下方式绘制绘图:
plot(df)
lines(df$x, exp(fit$fitted), col = 2, lwd = 2) ## red line
请注意我使用exp(fit$fitted)
,因为我们适合log(y)
的模型,现在我们将回到原始尺度。
<强>备注强>
正如@BenBolker所说,更简单的规范是:
fit <- lm(log(y/10000) ~ x - 1, data = df)
或
fit <- lm(log(y) - log(10000) ~ x - 1, data = df)
但现在响应变量不是log(y)
而是log(y/10000)
,所以当你制作情节时,你需要:
lines(df$x, 10000 * exp(fit$fitted), col = 2, lwd = 2)
使用nls()
使用nls()
的正确方法如下:
nls(y ~ 10000 * exp(r * x), data = df, start = list(r = 0.1))
由于非线性曲线拟合需要迭代,因此需要起始值,并且必须通过参数start
提供。
现在,如果您尝试使用此代码,您将获得:
Error in nls(y ~ 10000 * exp(r * x), data = df, start = list(r = 0.1)) :
number of iterations exceeded maximum of 50
问题是因为您的数据准确,没有噪音。阅读?nls
:
Warning:
*Do not use ‘nls’ on artificial "zero-residual" data.*
因此,使用nls()
作为您的玩具数据集df
不起作用。
让我们回过头来检查lm()
中的拟合模型:
fit$residuals
# 1 2 3 4 5
#-2.793991e-16 -1.145239e-16 -2.005405e-15 -5.498411e-16 3.094618e-15
# 6 7 8
# 1.410007e-15 -1.099682e-15 -1.007937e-15
在任何地方,残差基本上都是0,lm()
在这种情况下非常合适。
<强>后续强>
我无法弄清楚的最后一件事是
r
的公式规范中没有使用参数lm
。
lm
和nls
之间的公式实际上存在一些差异。也许你可以这样理解:
lm()
的公式称为模型公式,您可以从?formula
中读取该公式。它在R中非常基础。模型拟合例程使用它,如lm
,glm
,而许多函数都有公式方法,如model.matrix
,aggregate
,{{1}等等。boxplot
的公式更像是一个函数规范,并没有广泛使用。执行非线性迭代的许多其他函数(如nls()
)将不接受公式但直接接受函数。因此,只需将optim
视为特例。使用线性模型这样做是否有意义?我想在这里模拟的只是使用Malthusian增长模型。
严格地说,给出真实的人口数据(当然有噪音),使用nls()
进行曲线拟合,或使用nls()
进行泊松响应GLM比拟合线性模型有更好的理由。 glm(, family = poisson)
对您的数据的调用将是:
glm()
(您可能需要先了解GLM是什么。)但由于您的数据没有噪音,因此在使用时会收到警告信息。
然而,就计算复杂性而言,首先采用glm(y ~ x - 1, family = poisson(), data = df, offset = rep(log(10000), nrow(df)))
变换来使用线性模型是一个明显的胜利。在统计建模中,变量变换非常常见,因此没有令人信服的理由拒绝使用线性模型来估计人口增长率。 p>
作为完整的图片,我建议您尝试所有三种方法来获取真实数据(或嘈杂的玩具数据)。估计和预测会有一些差异,但不太可能很好。
<强>&#34;跟踪随访&#34; 强>
哈哈,再次感谢@Ben。对于log
,我们也可以尝试:
glm()
对于glm(y ~ x - 1 + offset(log(10000)), family = gaussian(link="log"))
规范,我们可以在offset
/ offset
中使用lm
参数,也可以像Ben一样使用glm
函数。