使用lm(),nls()(和glm()?)来估算马尔萨斯增长模型中的人口增长率

时间:2016-06-23 20:35:09

标签: r regression glm lm nls

我的问题与估算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()合理吗?

1 个答案:

答案 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

fit

请注意我使用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

lmnls之间的公式实际上存在一些差异。也许你可以这样理解:

  • lm()的公式称为模型公式,您可以从?formula中读取该公式。它在R中非常基础。模型拟合例程使用它,如lmglm,而许多函数都有公式方法,如model.matrixaggregate,{{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))) 变换来使用线性模型是一个明显的胜利。在统计建模中,变量变换非常常见,因此没有令人信服的理由拒绝使用线性模型来估计人口增长率。

作为完整的图片,我建议您尝试所有三种方法来获取真实数据(或嘈杂的玩具数据)。估计和预测会有一些差异,但不太可能很好。

<强>&#34;跟踪随访&#34;

哈哈,再次感谢@Ben。对于log,我们也可以尝试:

glm()

对于glm(y ~ x - 1 + offset(log(10000)), family = gaussian(link="log")) 规范,我们可以在offset / offset中使用lm参数,也可以像Ben一样使用glm函数。