2

在听取了@PhilipLeifeld 的建议后,我正在根据自己的进度重新撰写这篇文章(请参阅下面的评论部分)。

我试图将clmm输出放到乳胶中,使用texreg. 由于该包不支持clmm其默认模式,因此我尝试使用extract功能扩展该包(请参阅Print "beautiful" tables for h2o models in R 中的答案部分)。同时,我发现https://gist.github.com/kjgarza/340201f6564ca941fe25上发布的代码可以作为我的起点;我将代码称为下面的基线代码。以下模型(结果)非常能代表我的实际代码。

library(ordinal)
library(texreg)
d<-data.frame(wine)
result<-clmm(rating~ 1+temp+contact+(1+temp|judge), data=d)

我想在乳胶表中显示的是随机效应组件,它们在基线代码中被省略。以下是摘要输出的一部分。

summary(result)

Random effects:
 Groups Name        Variance Std.Dev. Corr  
 judge  (Intercept) 1.15608  1.0752         
        tempwarm    0.02801  0.1674   0.649 
 Number of groups:  judge 9 

具体来说,我想显示方差(和组数);我不需要相关部分。在处理基线代码时,我还了解到“texreg”仅允许有限的一组参数用于乳胶显示,并且“include.variance”选项与我的目标相关。因此,我尝试将随机效果组件添加到“gof”参数中,因为在基线代码中包含“include.variance”选项。

这是我所做的。首先,我在定义 extract.clmm 函数的部分添加了“include.variance”。

extract.clmm <- function(model, include.thresholds = TRUE, include.aic = TRUE, 
                     include.bic = TRUE, include.loglik = TRUE, include.variance = TRUE, oddsratios = TRUE, conf.level= 0.95, include.nobs = TRUE, ...) {
s <- summary(model, ...)

tab <- s$coefficients
thresh <- tab[rownames(tab) %in% names(s$alpha), ]
threshold.names <- rownames(thresh)
threshold.coef <- thresh[, 1]
threshold.se <- thresh[, 2]
threshold.pval <- thresh[, 4]
beta <- tab[rownames(tab) %in% names(s$beta), ]
beta.names <- rownames(beta)
beta.coef <- beta[, 1]
beta.se <- beta[, 2]
beta.pval <- beta[, 4]

然后,我添加了以下三行。

### for random effect components###   
rand<-s$ST[[1]]
rand.names<-rownames(rand)
rand.var<-rand[,1]

以下部分是我另外包含在基线代码中的部分(“include.variance”)。

if (include.variance == TRUE) {       
    gof.names <- c(gof.names, rand.names)
    gof <- c(gof, rand)
    gof.decimal <- c(gof.decimal, TRUE)   
}

运行 extract.clmm 函数后,我运行了以下命令。

test<-extract.clmm(result, include.variance=TRUE, oddsratios=FALSE)

然后,我收到一条错误消息:validationMethod(object) 中的错误:gof.names 和 gof 必须具有相同的长度!虽然我发现“结果”的情况下“rand”和“rand.names”的长度是4和2,但我不知道如何处理。任何意见将不胜感激。提前致谢。

4

2 回答 2

4

让我们首先重写您的测试用例,使其同时包含一个具有随机效应的模型 ( clmm) 和一个没有随机效应的模型 ( clm),两者都来自ordinal包。这将允许我们检查extract.clmm我们将要编写的函数是否产生格式与包中现有extract.clm函数兼容的结果texreg

library("ordinal")
library("texreg")
d <- data.frame(wine)
result.clmm <- clmm(rating ~ 1 + temp + contact + (1 + temp|judge), data = d)
result.clm <- clm(rating ~ 1 + temp + contact, data = d)

现有clm的泛型extract函数方法texreg如下所示,我们可以将其用作编写clmm方法的模板,因为两种对象类型的结构都类似:

# extension for clm objects (ordinal package)
extract.clm <- function(model, include.thresholds = TRUE, include.aic = TRUE, 
    include.bic = TRUE, include.loglik = TRUE, include.nobs = TRUE, ...) {
  s <- summary(model, ...)

  tab <- s$coefficients
  thresh <- tab[rownames(tab) %in% names(s$aliased$alpha), , drop = FALSE]
  threshold.names <- rownames(thresh)
  threshold.coef <- thresh[, 1]
  threshold.se <- thresh[, 2]
  threshold.pval <- thresh[, 4]
  beta <- tab[rownames(tab) %in% names(s$aliased$beta), , drop = FALSE]
  beta.names <- rownames(beta)
  beta.coef <- beta[, 1]
  beta.se <- beta[, 2]
  beta.pval <- beta[, 4]
  if (include.thresholds == TRUE) {
    names <- c(beta.names, threshold.names)
    coef <- c(beta.coef, threshold.coef)
    se <- c(beta.se, threshold.se)
    pval <- c(beta.pval, threshold.pval)
  } else {
    names <- beta.names
    coef <- beta.coef
    se <- beta.se
    pval <- beta.pval
  }

  n <- nobs(model)
  lik <- logLik(model)[1]
  aic <- AIC(model)
  bic <- BIC(model)
  gof <- numeric()
  gof.names <- character()
  gof.decimal <- logical()
  if (include.aic == TRUE) {
    gof <- c(gof, aic)
    gof.names <- c(gof.names, "AIC")
    gof.decimal <- c(gof.decimal, TRUE)
  }
  if (include.bic == TRUE) {
    gof <- c(gof, bic)
    gof.names <- c(gof.names, "BIC")
    gof.decimal <- c(gof.decimal, TRUE)
  }
  if (include.loglik == TRUE) {
    gof <- c(gof, lik)
    gof.names <- c(gof.names, "Log Likelihood")
    gof.decimal <- c(gof.decimal, TRUE)
  }
  if (include.nobs == TRUE) {
    gof <- c(gof, n)
    gof.names <- c(gof.names, "Num.\ obs.")
    gof.decimal <- c(gof.decimal, FALSE)
  }

  tr <- createTexreg(
      coef.names = names, 
      coef = coef, 
      se = se, 
      pvalues = pval, 
      gof.names = gof.names, 
      gof = gof, 
      gof.decimal = gof.decimal
  )
  return(tr)
}

setMethod("extract", signature = className("clm", "ordinal"), 
    definition = extract.clm)

对象的第一个区别clmm是系数等不是存储在summary(model)$aliased$alphaand下summary(model)$aliased$beta,而是直接存储在summary(model)$alphaand下summary(model)$beta

我们需要做的第二件事是为组数和随机方差添加拟合优度元素。

组的数量显然存储在 下summary(model)$dims$nlev.gf,具有不同条件变量的多个条目。所以这很容易。

随机方差没有存储在任何地方,所以我们需要在包的源代码中ordinal查找它。我们可以看到该print.summary.clmm函数使用了一个内部辅助函数formatVC来打印方差。该函数包含在同一个R脚本中,基本上只是进行格式化并调用另一个名为varcov(也包含在同一文件中)的内部辅助函数来计算方差。反过来,该函数计算 的转置叉积model$ST以获得方差。我们可以直接在extract.clmm函数的 GOF 块中简单地做同样的事情,例如,使用diag(s$ST[[1]] %*% t(s$ST[[1]]))对于第一个随机效应。我们只需要确保我们对所有随机效果都这样做,这意味着我们需要将它放在一个循环中并用[[1]][[i]].

该函数的最终clmm方法extract可能如下所示:

# extension for clmm objects (ordinal package)
extract.clmm <- function(model, include.thresholds = TRUE,
    include.loglik = TRUE, include.aic = TRUE,  include.bic = TRUE,
    include.nobs = TRUE, include.groups = TRUE, include.variance = TRUE, ...) {
  s <- summary(model, ...)

  tab <- s$coefficients
  thresh <- tab[rownames(tab) %in% names(s$alpha), ]
  threshold.names <- rownames(thresh)
  threshold.coef <- thresh[, 1]
  threshold.se <- thresh[, 2]
  threshold.pval <- thresh[, 4]
  beta <- tab[rownames(tab) %in% names(s$beta), ]
  beta.names <- rownames(beta)
  beta.coef <- beta[, 1]
  beta.se <- beta[, 2]
  beta.pval <- beta[, 4]

  if (include.thresholds == TRUE) {
    cfnames <- c(beta.names, threshold.names)
    coef <- c(beta.coef, threshold.coef)
    se <- c(beta.se, threshold.se)
    pval <- c(beta.pval, threshold.pval)
  } else {
    cfnames <- beta.names
    coef <- beta.coef
    se <- beta.se
    pval <- beta.pval
  }

  gof <- numeric()
  gof.names <- character()
  gof.decimal <- logical()
  if (include.loglik == TRUE) {
    lik <- logLik(model)[1]
    gof <- c(gof, lik)
    gof.names <- c(gof.names, "Log Likelihood")
    gof.decimal <- c(gof.decimal, TRUE)
  }
  if (include.aic == TRUE) {
    aic <- AIC(model)
    gof <- c(gof, aic)
    gof.names <- c(gof.names, "AIC")
    gof.decimal <- c(gof.decimal, TRUE)
  }
  if (include.bic == TRUE) {
    bic <- BIC(model)
    gof <- c(gof, bic)
    gof.names <- c(gof.names, "BIC")
    gof.decimal <- c(gof.decimal, TRUE)
  }
  if (include.nobs == TRUE) {
    n <- nobs(model)
    gof <- c(gof, n)
    gof.names <- c(gof.names, "Num.\ obs.")
    gof.decimal <- c(gof.decimal, FALSE)
  }
  if (include.groups == TRUE) {
    grp <- s$dims$nlev.gf
    grp.names <- paste0("Groups (", names(grp), ")")
    gof <- c(gof, grp)
    gof.names <- c(gof.names, grp.names)
    gof.decimal <- c(gof.decimal, rep(FALSE, length(grp)))
  }
  if (include.variance == TRUE) {
    var.names <- character()
    var.values <- numeric()
    for (i in 1:length(s$ST)) {
      variances <- diag(s$ST[[i]] %*% t(s$ST[[i]]))
      var.names <- c(var.names, paste0("Variance: ", names(s$ST)[[i]], ": ", 
          names(variances)))
      var.values <- c(var.values, variances)
    }
    gof <- c(gof, var.values)
    gof.names <- c(gof.names, var.names)
    gof.decimal <- c(gof.decimal, rep(TRUE, length(var.values)))
  }

  tr <- createTexreg(
      coef.names = cfnames, 
      coef = coef, 
      se = se, 
      pvalues = pval, 
      gof.names = gof.names, 
      gof = gof, 
      gof.decimal = gof.decimal
  )
  return(tr)
}

setMethod("extract", signature = className("clmm", "ordinal"), 
    definition = extract.clmm)

您可以在运行时执行代码,并且texreg应该能够从clmm对象创建表,包括随机方差。我会将此代码添加到下一个texreg版本中。

您可以将其应用于您的示例,如下所示:

screenreg(list(result.clmm, result.clm), single.row = TRUE)

结果clmmclm对象兼容,正如您在输出中看到的那样:

==================================================================
                              Model 1            Model 2          
------------------------------------------------------------------
tempwarm                        3.07 (0.61) ***    2.50 (0.53) ***
contactyes                      1.83 (0.52) ***    1.53 (0.48) ** 
1|2                            -1.60 (0.69) *     -1.34 (0.52) ** 
2|3                             1.50 (0.60) *      1.25 (0.44) ** 
3|4                             4.22 (0.82) ***    3.47 (0.60) ***
4|5                             6.11 (1.02) ***    5.01 (0.73) ***
------------------------------------------------------------------
Log Likelihood                -81.55             -86.49           
AIC                           181.09             184.98           
BIC                           201.58             198.64           
Num. obs.                      72                 72              
Groups (judge)                  9                                 
Variance: judge: (Intercept)    1.16                              
Variance: judge: tempwarm       0.03                              
==================================================================
*** p < 0.001, ** p < 0.01, * p < 0.05

如果需要,您可以使用参数include.variances == FALSEinclude.groups == FALSE关闭差异和组大小的报告。

于 2016-09-15T09:37:31.810 回答
2

作为对@Philip 回答的快速评论,在新版本或 R 工作室中,以下内容不返回矩阵:

thresh <- tab[rownames(tab) %in% names(s$alpha), ]

这会导致以下代码返回错误。但是,对此的快速修复可以是:

thresh <- subset.matrix(tab, rownames(tab) %in% names(s$alpha) )
beta <- subset.matrix(tab, rownames(tab) %in% names(s$beta) )
于 2017-01-07T16:24:52.870 回答