【问题标题】:Using lm(), nls() (and glm()?) to estimate population growth rate in Malthusian growth model使用 lm()、nls()(和 glm()?)估计马尔萨斯增长模型中的人口增长率
【发布时间】:2016-10-26 08:41:07
【问题描述】:

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

【问题讨论】:

    标签: r regression glm lm nls


    【解决方案1】:

    使用 lm()

    请阅读?formula 以获得正确的公式说明。现在我会继续假设你已经阅读了。

    首先,您的模型在对 LHS 和 RHS 进行 log 变换后,变为:

    log(y) = log(10000) + r * x
    

    常数是一个已知值,不能估计。这样的常量在lm 中称为offset

    你应该像这样使用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 的列表。请参阅?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() 在这种情况下完全适合。


    跟进

    我无法弄清楚的最后一件事是为什么lm 的公式规范中没有使用参数r

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

    • lm() 的公式称为模型公式,可以从?formula 阅读。它在 R 中非常基础。模型拟合例程使用它,例如 lmglm,而许多函数具有公式方法,例如 model.matrixaggregateboxplot 等。
    • nls() 的公式更像是一个函数规范,并没有被广泛使用。许多其他执行非线性迭代的函数,如optim,将不接受公式,而是直接接受函数。因此,只需将 nls() 视为特例即可。

    那么使用线性模型是否有意义?我在这里尝试建模的只是使用马尔萨斯增长模型。

    严格来说,给出真实的人口数据(当然有噪声),使用nls() 进行曲线拟合,或使用glm(, family = poisson) 进行泊松响应 GLM 比拟合线性模型具有更好的基础。 glm() 调用您的数据将是:

    glm(y ~ x - 1, family = poisson(), data = df, offset = rep(log(10000), nrow(df)))
    

    (您可能需要先了解 GLM 是什么。)但是由于您的数据没有噪音,因此您在使用时会收到警告消息。

    但是,就计算复杂度而言,通过首先进行log 变换来使用线性模型是明显的胜利。在统计建模中,变量变换非常普遍,因此没有令人信服的理由拒绝使用线性模型来估计人口增长率。​​p>

    总体而言,我建议您尝试所有三种方法来处理真实数据(或嘈杂的玩具数据)。估计和预测会有一些差异,但不会很大。

    “后续跟进”

    哈哈,再次感谢@Ben。对于glm(),我们也可以试试:

    glm(y ~ x - 1 + offset(log(10000)), family = gaussian(link="log"))
    

    对于offset 规范,我们可以在lm/glm 中使用offset 参数,或者像Ben 那样使用offset() 函数。

    【讨论】:

    • 对于线性模型,您甚至不需要偏移:log(y)-log(10000) ~ x -1 应该可以工作(尽管偏移可能更清晰)
    • 感谢您的帮助!但是我不能输入log(y) = log(10000) + r * x,因为它显示could not find function "log&lt;-"。我做错了吗?
    • 我实际上有点困惑,但现在阅读拦截,我更清楚地理解它,仍然有问题的一件事是为什么 lm 导致列表 13。但在这种情况下,我不能使用 lm 的拟合来绘制情节!我正在使用plot(df),然后是lines(x,fit)fit 基本上就是lm(log(y) ~ x - 1, data = df, offset = rep(log(10000), nrow(df)))
    • 很棒的回复。谢谢!它现在为我清除了一切。我无法弄清楚的最后一件事是为什么lm 中没有使用参数r,我特别质疑这一点,因为我正在做的r 是我的模型在一项生物信息学任务,因此非常重要。
    • glm(y~x-1 + offset(log(10000)), family=gaussian(link="log")) 是另一种可能
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-02
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    相关资源
    最近更新 更多