如何计算lm系数,使测试统计数据保持有效

时间:2018-04-19 08:56:26

标签: r

我需要一个所谓的简单任务的帮助,但我无法找到解决方案。假设适合像

这样的简单线性模型

model <- lm(Y~ a_1 + a_2, data=mydata)

现在理想情况下,在我的输出中,我想将a_1上的系数报告为a_2/a_1(=估算比率!)的比率,以便我的测试统计数据即标准误差正确。这是一个可重复的示例,说明如何计算我想在输出中报告的估算值:

a_2 <- 1:20
a_1 <- 20:40
Y <- 1
mydata <- as.data.frame(cbind(Y, a_1, a_2))
model <- lm(Y~a_1+a_2, data=mydata)
coef <- coefficients(model)
coef[2] <- coef[3]/coef[2]     # the estimate I want to report in my output

我正在使用stargazer作为我的输出stargazer(model),并且该软件包提供了apply.coef功能,但我不知道这是否可以实现我正在寻找的功能。或者有没有办法直接在我的lm函数中指定它?

1 个答案:

答案 0 :(得分:1)

这可能会超出您的要求,但我想演示如何使用贝叶斯模型rstan来获得模型参数派生数量的实际估算,例如简单线性模型中两个参数的比率。

(p)贝叶斯方法的一个好处是,可以访问并稳健地处理所有参数的完整后验密度的传播。因此,不确定性会自动适当地传播到任何作为参数函数的自定义派生量。

以下是使用R库Ginzberg中的car数据的已完成示例。

  1. 加载rstancar库。

    library(rstan);
    library(car);
    
  2. 定义一个隐式均匀先验的简单线性模型;均匀的先验通常不是一个好主意。我们将它们保留在这里,以使结果与lm模型的结果更加可比。

    model <- "
    data {
        int N;            // Number of observations
        int K;            // Number of model parameters
        real y[N];        // Response vector
        matrix[N,K] X;    // Data/model matrix
    }
    parameters {
        vector[K] beta;   // Model coefficients
        real sigma;       // Standard deviation
    }
    
    model {
        y ~ normal(X * beta, sigma);   // Likelihood
    }
    
    generated quantities {
        real ratio;
        ratio = beta[2] / beta[3];
    }"
    

    请注意我们计算派生generated quantities参数的ratio块作为beta[2]beta[3]的比率。

  3. 根据Ginzberg抑郁症数据,我们使用非零截距模拟depression ~ simplicity + fatalism

    ## Sample data
    # Ginzberg data on depression included in R library "car"
    X <- model.matrix(~ simplicity + fatalism, data = Ginzberg);
    
  4. 适合Stan模型并显示合适的结果。

    # Fit the model in Stan
    fit.stan <- stan(
        model_code = model,
        data = list(N = nrow(X), K = 3, y = Ginzberg$depression, X = X))
    fit.stan;
    #Inference for Stan model: d0cfe0c2eab6991c34e2d242b74ea832.
    #4 chains, each with iter=2000; warmup=1000; thin=1;
    #post-warmup draws per chain=1000, total post-warmup draws=4000.
    #
    #         mean se_mean   sd  2.5%   25%   50%   75% 97.5% n_eff Rhat
    #beta[1]  0.20    0.00 0.10  0.01  0.13  0.20  0.26  0.39  2718    1
    #beta[2]  0.38    0.00 0.11  0.17  0.31  0.38  0.45  0.60  1887    1
    #beta[3]  0.42    0.00 0.10  0.21  0.35  0.42  0.49  0.61  1896    1
    #sigma    0.36    0.00 0.03  0.30  0.34  0.35  0.38  0.42  3042    1
    #ratio    0.65    0.02 1.40  0.02  0.32  0.52  0.80  1.88  3401    1
    #lp__    44.19    0.04 1.48 40.40 43.46 44.51 45.29 46.06  1332    1
    #
    #Samples were drawn using NUTS(diag_e) at Thu Apr 19 21:58:12 2018.
    #For each parameter, n_eff is a crude measure of effective sample size,
    #and Rhat is the potential scale reduction factor on split chains (at
    #convergence, Rhat=1).
    

    请注意,beta[1]是偏移量,beta[2]simplicity系数,beta[3]fatalism系数。 ratio是派生的simplicity/fatalism系数比率。 sigma是正常错误术语的标准偏差。

    由于我们定义了一个&#34;生成的数量&#34;,我们得到了我们派生的ratio参数的完整后验分布(以及标准偏差,置信区间等)。

  5. 因为它很容易,我们还绘制参数估计值,包括置信区间。我们可以看到与派生的ratio参数估计相关的较大不确定性。

    plot(fit.stan);
    #ci_level: 0.8 (80% intervals)
    #outer_level: 0.95 (95% intervals)
    
  6. enter image description here

    1. 我们可以将参数估算值与lm的点估算值进行比较。

      fit.lm <- lm(depression ~ simplicity + fatalism, data = Ginzberg);
      coef.est <- summary(fit.lm)$coef[, 1];
      coef.sd <- summary(fit.lm)$coef[, 2];
      cbind.data.frame(coef.est, coef.sd);
      #             coef.est    coef.sd
      #(Intercept) 0.2026931 0.09472399
      #simplicity  0.3795328 0.10063518
      #fatalism    0.4177744 0.10063504
      

      我们现在还可以使用Gauss' law for the propagation of uncertainties计算比率并从两个参数传播标准偏差。

      ratio <- unname(coef.est[2] / coef.est[3]);
      ratio.sd <- unname(ratio * sqrt((coef.sd[2]/coef.est[2])^2 + (coef.sd[3]/coef.est[3])^2));
      cbind.data.frame(ratio, ratio.sd);
      #      ratio  ratio.sd
      #1 0.9084635 0.3254435
      

      很明显,这种天真的做法低估了ratio中的不确定性