打印"漂亮" R中h2o模型的表格

时间:2016-08-11 10:39:32

标签: r h2o stargazer texreg

R有多个软件包有助于打印"漂亮"表(LaTeX / HTML / TEXT)来自统计模型输出AND,可以轻松比较替代模型规范的结果。

其中一些软件包包括apsrtablextablememisctexregoutregstargazer(例如,请参阅此处: https://www.r-statistics.com/2013/01/stargazer-package-for-beautiful-latex-tables-from-r-statistical-models-output/)。

是否有支持R软件包模型的类似h2o软件包?

这是一个带有h2o的两个简单GLM模型的示例,我喜欢将它们彼此相邻打印为" beautiful"表。

# Load package and setup h2o
library(h2o)
localH2O <- h2o.init(ip = 'localhost', port = 54321, max_mem_size = '4g')

# Load data
prostatePath <- system.file("extdata", "prostate.csv", package = "h2o")
prostate.hex <- h2o.importFile(path = prostatePath, destination_frame = "prostate.hex")

# Run GLMs
model.output.1 <- h2o.glm(y = "CAPSULE", x = c("RACE","PSA","DCAPS"),
  training_frame = prostate.hex,family = "binomial", nfolds = 0, 
  alpha = 0.5, lambda_search = FALSE)
model.output.2 <- h2o.glm(y = "CAPSULE", x = c("AGE","RACE","PSA","DCAPS"), 
  training_frame = prostate.hex, family = "binomial", nfolds = 0, 
  alpha = 0.5, lambda_search = FALSE)

这是使用screenreg()包中的texreg使用常规GLM对象时的样子:

library(data.table)
library(texreg)
d <- fread(prostatePath)
model.output.1.glm <- glm(CAPSULE ~ RACE + PSA + DCAPS, data=d)
model.output.2.glm <- glm(CAPSULE ~ AGE + RACE + PSA + DCAPS, data=d)
screenreg(list(model.output.1.glm, model.output.2.glm))

enter image description here

3 个答案:

答案 0 :(得分:15)

texreg包裹作者在这里。 texreg基于通用函数,这意味着任何用户都可以为任意模型添加自定义extract方法,并使其与texreg一起使用。我将带您了解下面的内容。我希望这个详细的阐述能够帮助过去曾提出类似问题的其他人设计自己的texreg扩展名。

另请参见2013 paper in the Journal of Statistical Software中的第6节。首先,我将描述texreg架构如何更普遍地为您提供可能的概念。

texreg和通用extract函数

有三个函数:texreg(对于LaTeX输出),htmlreg(对于HTML输出,在大多数使用场景中也可以通过Word或Markdown解释)和screenreg (用于控制台中的ASCII文本输出)。这三个函数用于将一些清理后的信息(系数,标准误差,置信区间,p值,拟合度统计量,模型标签等)转换为相应的输出格式。这并不完美,可能更灵活,但我认为此时有很多自定义论据,包括booktabsdcolumn支持。因此,最大的挑战是首先获得清理过的模型信息。

这是通过向这三个函数中的任何一个提供texreg对象来完成的。 texreg对象只是系数等的容器,并且使用S4类正式定义。要创建texreg对象,您可以使用构造函数createTexreg(如帮助页面上所述),它接受所有不同的信息作为参数,例如标准错误等。或者(更好)您可以使用extract函数从某个估计模型中提取这些信息,并返回texreg对象以用于这三个函数中的任何一个。通常这样做的方法是将几个模型的列表移交给texregscreenreg等函数,此函数将在内部调用extract来创建{{1}对象然后处理来自这些对象的信息。

但是,将texreg函数的调用输出保存到对象,可能操作此extract对象,然后调用texreg函数同样有效。被操纵的对象将其显示为表格。这样可以灵活地调整结果。

早些时候,我提到该软件包使用泛型函数。这意味着texreg函数是通用的,因为您可以为任意类型的模型注册它的方法。例如,如果extract函数不知道如何处理extract个对象以及如何从这样的对象中提取相关信息,那么您可以编写一个方法来执行此操作并将其注册到{ {1}}功能。下面,我将逐步引导您完成这一过程,希望人们能够从这个详细的阐述中学习并开始编写自己的扩展。 (注意:如果有人开发了一个有用的方法,请给我发电子邮件,我可以将它包含在下一个h2o版本中。)还值得指出的是,该软件包的源文件包含70多个示例。 extract方法,您可以将其用作模板。这些示例存储在文件texreg中。

识别类标签并设置extract方法

第一步是识别对象的类名。在您的示例中,R/extract.R返回以下类标签:&#34; H2OBinomialModel&#34;和&#34; h2o&#34;。第一个标签是更具体的标签,第二个标签是更普遍的标签。如果所有extract模型对象都以类似的方式构造,那么为class(model.output.1)对象编写扩展名是有意义的,然后在方法中决定如何继续使用特定模型。由于我对h2o软件包几乎一无所知,在这种情况下,我更倾向于使用更具体的h2o方法来处理h2o个对象。如果我们愿意,可以稍后调整。

extract方法的结构如下:你编写一个名为H2OBinomialModel的函数(替换&#34; xyz&#34;通过类标签),至少有一个名为{{1}的参数},它接受​​模型对象(例如,在您的示例中为extract),将一些代码放入正文中,从extract.xyz对象中提取相关信息,使用以下对象创建model对象model.output.1构造函数,并返回此对象。这是一个空容器:

model

请注意,函数定义还包含texreg参数,该参数可用于应在createTexreg方法中移交给函数调用的自定义参数。

另请注意,函数定义正文中的第一行将模型摘要保存在名为extract.H2OBinomialModel <- function(model, ...) { s <- summary(model) # extract information from model and summary object here # then create and return a texreg object (replace NULL with actual values): tr <- createTexreg( coef.names = NULL, # character vector of coefficient labels coef = NULL, # numeric vector with coefficients se = NULL, # numeric vector with standard error values pvalues = NULL, # numeric vector with p-values gof.names = NULL, # character vector with goodness-of-fit labels gof = NULL, # numeric vector of goodness-of-fit statistics gof.decimal = NULL # logical vector: GOF statistic has decimal points? ) return(tr) } 的对象中。这通常很有用,因为许多包编写者决定将一些信息存储在摘要中的更简单版本中,因此通常应该将模型及其摘要都视为有用的信息源。在某些情况下,可能必须查看相应包中的摘要方法的实际定义,以了解在调用...命令时如何计算摘要页面上显示的信息,因为不是全部{ {1}}方法存储extract对象中显示的不同元素。

s对象中找到正确的信息

下一步是检查对象并找到应在最终表中显示的所有细节。通过查看summary的输出,我猜想以下部分应构成表格底部的GOF块:

summary

以下部分可能构成表格中间的系数块:

summary

在许多情况下,摘要包含相关信息,但在此打印模型会产生我们需要的信息。我们需要在H2OBinomialModel对象(或其摘要,如果适用)中找到所有这些内容。为此,有几个有用的命令。其中包括model.output.1MSE: 0.202947 R^2: 0.1562137 LogLoss: 0.5920097 Mean Per-Class Error: 0.3612191 AUC: 0.7185655 Gini: 0.4371311 Null Deviance: 512.2888 Residual Deviance: 449.9274 AIC: 457.9274 和类似的命令。

让我们从系数块开始。调用Coefficients: glm coefficients names coefficients standardized_coefficients 1 Intercept -1.835223 -0.336428 2 RACE -0.625222 -0.193052 3 DCAPS 1.314428 0.408336 4 PSA 0.046861 0.937107 显示S4对象中有一个名为model.output.1的插槽。我们可以通过调用str(model.output.1)来查看其内容。结果是一个包含多个命名元素的列表,其中包括names(summary(model.output.1))。因此,我们可以通过调用str(model)来访问系数表。结果是一个数据框,我们可以使用model运算符访问其中的列。特别是,我们需要名称和系数。这里有两种类型的系数,标准化和非标准化,我们可以稍后在我们的提取方法中添加一个参数,让用户决定他或她想要什么。以下是我们如何提取系数及其标签:

model.output.1@model

据我所知,对象中没有存储标准错误或p值。如果我们希望这样做,我们可以编写一些额外的代码来计算它们,但在这里我们将重点关注那些作为模型输出的一部分提供的东西。

重要的是,我们不应覆盖coefficients_table中的任何现有函数名称,例如model.output.1@model$coefficients_table$。虽然这样做应该在技术上有效,因为代码在以后的函数中执行,这很容易在尝试时导致混淆,所以你应该更好地避免这种情况。

接下来,我们需要找到拟合优度统计数据。通过仔细检查coefnames <- model.output.1@model$coefficients_table$names coefs <- model.output.1@model$coefficients_table$coefficients coefs.std <- model.output.1@model$coefficients_table$standardized_coefficients 的输出,我们发现拟合优度统计数据包含在R下的几个位中。让我们将它们保存到一些易于访问的对象中:

names

在某些情况下,但不是在这里,包的作者编写通用函数的方法,可用于提取一些常见信息,如观察数(coef),AIC(str(model.output.1) ),BIC(model@model$training_metrics@metrics),偏差(mse <- model.output.1@model$training_metrics@metrics$MSE r2 <- model.output.1@model$training_metrics@metrics$r2 logloss <- model.output.1@model$training_metrics@metrics$logloss mpce <- model.output.1@model$training_metrics@metrics$mean_per_class_error auc <- model.output.1@model$training_metrics@metrics$AUC gini <- model.output.1@model$training_metrics@metrics$Gini nulldev <- model.output.1@model$training_metrics@metrics$null_deviance resdev <- model.output.1@model$training_metrics@metrics$residual_deviance aic <- model.output.1@model$training_metrics@metrics$AIC )或对数似然(nobs(model))。所以这些是你可能想先尝试的东西;但是AIC(model)包似乎没有提供这样的便利方法。

将信息添加到BIC(model)功能

现在我们已经找到了我们需要的所有信息,我们可以将它们添加到我们上面定义的deviance(model)函数中。

但是,我们希望让用户决定他或她是否更喜欢原始系数或标准化系数,并且我们希望让用户决定应该报告哪种拟合优度统计数据,因此我们添加了各种逻辑参数函数头然后在函数内部使用if-conditions来检查我们是否应该在生成的logLik(model)[[1]]对象中嵌入相应的统计信息。

在这种情况下,我们也删除了行h2o,因为我们实际上并不需要摘要中的任何信息,因为我们在模型对象中找到了所需的一切。

完整的功能可能如下所示:

extract.H2OBinomialModel

对于拟合优度块,您可以看到我首先创建了空向量,然后使用其他统计信息填充它们,前提是用户使用相应的参数打开了相应的统计信息。

extract.H2OBinomialModel逻辑向量表示每个GOF统计数据是否有小数位(texreg)或不具有s <- summary(model),例如观察数量。

最后,需要将新函数注册为通用# extension for H2OBinomialModel objects (h2o package) extract.H2OBinomialModel <- function(model, standardized = FALSE, include.mse = TRUE, include.rsquared = TRUE, include.logloss = TRUE, include.meanerror = TRUE, include.auc = TRUE, include.gini = TRUE, include.deviance = TRUE, include.aic = TRUE, ...) { # extract coefficient table from model: coefnames <- model@model$coefficients_table$names if (standardized == TRUE) { coefs <- model@model$coefficients_table$standardized_coefficients } else { coefs <- model@model$coefficients_table$coefficients } # create empty GOF vectors and subsequently add GOF statistics from model: gof <- numeric() gof.names <- character() gof.decimal <- logical() if (include.mse == TRUE) { mse <- model@model$training_metrics@metrics$MSE gof <- c(gof, mse) gof.names <- c(gof.names, "MSE") gof.decimal <- c(gof.decimal, TRUE) } if (include.rsquared == TRUE) { r2 <- model@model$training_metrics@metrics$r2 gof <- c(gof, r2) gof.names <- c(gof.names, "R^2") gof.decimal <- c(gof.decimal, TRUE) } if (include.logloss == TRUE) { logloss <- model@model$training_metrics@metrics$logloss gof <- c(gof, logloss) gof.names <- c(gof.names, "LogLoss") gof.decimal <- c(gof.decimal, TRUE) } if (include.meanerror == TRUE) { mpce <- model@model$training_metrics@metrics$mean_per_class_error gof <- c(gof, mpce) gof.names <- c(gof.names, "Mean Per-Class Error") gof.decimal <- c(gof.decimal, TRUE) } if (include.auc == TRUE) { auc <- model@model$training_metrics@metrics$AUC gof <- c(gof, auc) gof.names <- c(gof.names, "AUC") gof.decimal <- c(gof.decimal, TRUE) } if (include.gini == TRUE) { gini <- model@model$training_metrics@metrics$Gini gof <- c(gof, gini) gof.names <- c(gof.names, "Gini") gof.decimal <- c(gof.decimal, TRUE) } if (include.deviance == TRUE) { nulldev <- model@model$training_metrics@metrics$null_deviance resdev <- model@model$training_metrics@metrics$residual_deviance gof <- c(gof, nulldev, resdev) gof.names <- c(gof.names, "Null Deviance", "Residual Deviance") gof.decimal <- c(gof.decimal, TRUE, TRUE) } if (include.aic == TRUE) { aic <- model@model$training_metrics@metrics$AIC gof <- c(gof, aic) gof.names <- c(gof.names, "AIC") gof.decimal <- c(gof.decimal, TRUE) } # create texreg object: tr <- createTexreg( coef.names = coefnames, coef = coefs, gof.names = gof.names, gof = gof, gof.decimal = gof.decimal ) return(tr) } 函数的方法。这是通过一个简单的命令完成的:

gof.decimal

这里,TRUE的第一个参数是类标签,第二个参数是定义类的包。

总结一下,编写自定义扩展需要完成的唯一两件事是:1)编写提取方法,以及2)注册方法。也就是说,此代码可以在运行时执行,也不必插入任何包中。

但是,为方便起见,我已将FALSE方法添加到extract版本1.36.13,该版本可在CRAN上使用。

请注意,此处提供的解决方案不适用于任何先前版本的setMethod("extract", signature = className("H2OBinomialModel", "h2o"), definition = extract.H2OBinomialModel) ,因为以前的版本无法处理既没有标准错误也没有置信区间的模型。在我看来,这是一个相当专业的设置,我没有遇到只提供估算而没有任何不确定性措施的方案。我现在已经在className修正了这个问题。

尝试新的H2OBinomialModel方法

在运行时执行了函数定义和texreg命令后,可以使用以下命令创建表:

texreg

这是输出:

texreg

extract论证在这里是有道理的,因为我们不想要一个重要性图例,因为模型不会报告任何不确定性度量。

也可以抑制一些GOF指标和/或使用标准化系数:

setMethod

结果:

screenreg(list(model.output.1, model.output.2), custom.note = "")

可与====================================== Model 1 Model 2 -------------------------------------- Intercept -1.84 -1.11 RACE -0.63 -0.62 DCAPS 1.31 1.31 PSA 0.05 0.05 AGE -0.01 -------------------------------------- MSE 0.20 0.20 R^2 0.16 0.16 LogLoss 0.59 0.59 Mean Per-Class Error 0.36 0.38 AUC 0.72 0.72 Gini 0.44 0.44 Null Deviance 512.29 512.29 Residual Deviance 449.93 449.51 AIC 457.93 459.51 ======================================

一起使用的其他插槽

custom.note = ""构造函数在任何screenreg(list(model.output.1, model.output.2), custom.note = "", include.deviance = FALSE, include.auc = FALSE, standardized = TRUE) 方法中调用。上面的例子显示了一些简单的信息。除了示例中包含的详细信息外,====================================== Model 1 Model 2 -------------------------------------- Intercept -0.34 -0.34 RACE -0.19 -0.19 DCAPS 0.41 0.41 PSA 0.94 0.94 AGE -0.07 -------------------------------------- MSE 0.20 0.20 R^2 0.16 0.16 LogLoss 0.59 0.59 Mean Per-Class Error 0.36 0.38 Gini 0.44 0.44 AIC 457.93 459.51 ====================================== 个对象中还提供了以下插槽:

  • se:标准错误
  • pvalues:p值
  • ci.low:置信区间的下限
  • ci.up:置信区间的上限
  • model.name:当前模型的标题

请注意,应使用置信区间或标准误差和p值,而不是两者。

操纵createTexreg个对象

除了直接将模型移交给createTexregextracttexreg函数之外,还可以先将提取的信息保存到texreg对象并进行操作在显示或保存表格之前。增加的价值是,即使是对表的复杂更改也很容易以这种方式应用。例如,可以重命名系数或GOF统计数据,添加新行,重命名模型,修改值或更改系数或GOF统计数据的顺序。以下是如何执行此操作的方法:首先,调用screenreg函数将信息保存到texreg对象:

htmlreg

只需调用texreg即可显示extract对象的内容,其中显示以下输出:

texreg

或者,这是tr <- extract(model.output.1)

所示对象的结构
texreg

现在您可以以任意方式操纵此对象,例如,添加GOF统计信息:

tr

或者您可以更改系数的顺序:

No standard errors and p-values were defined for this texreg object.

                coef.
Intercept -1.83522343
RACE      -0.62522179
DCAPS      1.31442834
PSA        0.04686106

                             GOF dec. places
MSE                    0.2029470        TRUE
R^2                    0.1562137        TRUE
LogLoss                0.5920097        TRUE
Mean Per-Class Error   0.3612191        TRUE
AUC                    0.7185655        TRUE
Gini                   0.4371311        TRUE
Null Deviance        512.2888402        TRUE
Residual Deviance    449.9273825        TRUE
AIC                  457.9273825        TRUE

完成操作后,您可以在拨打电话时移交str(tr)对象而非原始模型,例如Formal class 'texreg' [package "texreg"] with 10 slots ..@ coef.names : chr [1:4] "Intercept" "RACE" "DCAPS" "PSA" ..@ coef : num [1:4] -1.8352 -0.6252 1.3144 0.0469 ..@ se : num(0) ..@ pvalues : num(0) ..@ ci.low : num(0) ..@ ci.up : num(0) ..@ gof.names : chr [1:9] "MSE" "R^2" "LogLoss" "Mean Per-Class Error" ... ..@ gof : num [1:9] 0.203 0.156 0.592 0.361 0.719 ... ..@ gof.decimal: logi [1:9] TRUE TRUE TRUE TRUE TRUE TRUE ... ..@ model.name : chr(0)

tr@gof.names <- c(tr@gof.names, "new statistic")
tr@gof <- c(tr@gof, 12)
tr@gof.decimal <- c(tr@gof.decimal, FALSE)

新结果将如下所示:

tr@coef.names <- tr@coef.names[c(4, 1, 2, 3)]
tr@coef <- tr@coef[c(4, 1, 2, 3)]

TL; DR

texreg可由用户自定义。只需编写如上所示的提取方法,并使用screenreg调用进行注册。我在latest texreg version 1.36.13中添加了screenreg(list(tr, model.output.2), custom.note = "") 方法,以及使用没有标准错误的模型(例如此错误)的错误修正。

答案 1 :(得分:1)

如果从模型输出中提取它们,则可以使用带有h2o的H2OTable的R xtable包(如果使用as.h2o(your_H2OTable)将H2OTable转换为H2OFrame,则使用knitr)。

例如,要根据模型的系数创建漂亮的表,首先需要使用model.output.1@model$coefficients_table提取系数表,然后使用xtable:xtable(prostate.glm@model$coefficients_table)打印出Latex代码。

对于并排视图,有多篇关于如何在knitr或xtablextable and sweave

中执行此操作的帖子

答案 2 :(得分:0)

不,目前没有这样做的包。 broom包不支持H2O模型 - 这很酷!也许这可能在未来发生。一旦有一种方法可以使用扫帚或类似的功能将模型输出“整理”到R data.frame中,那么xtable等将很好地工作。