R
有多个软件包有助于打印"漂亮"表(LaTeX / HTML / TEXT)来自统计模型输出AND,可以轻松比较替代模型规范的结果。
其中一些软件包包括apsrtable
,xtable
,memisc
,texreg
,outreg
和stargazer
(例如,请参阅此处: 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))
答案 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值,拟合度统计量,模型标签等)转换为相应的输出格式。这并不完美,可能更灵活,但我认为此时有很多自定义论据,包括booktabs
和dcolumn
支持。因此,最大的挑战是首先获得清理过的模型信息。
这是通过向这三个函数中的任何一个提供texreg
对象来完成的。 texreg
对象只是系数等的容器,并且使用S4类正式定义。要创建texreg
对象,您可以使用构造函数createTexreg
(如帮助页面上所述),它接受所有不同的信息作为参数,例如标准错误等。或者(更好)您可以使用extract
函数从某个估计模型中提取这些信息,并返回texreg
对象以用于这三个函数中的任何一个。通常这样做的方法是将几个模型的列表移交给texreg
或screenreg
等函数,此函数将在内部调用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.1
,MSE: 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
======================================
个对象中还提供了以下插槽:
请注意,应使用置信区间或标准误差和p值,而不是两者。
createTexreg
个对象除了直接将模型移交给createTexreg
,extract
或texreg
函数之外,还可以先将提取的信息保存到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)]
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或xtable或xtable and sweave
中执行此操作的帖子答案 2 :(得分:0)
不,目前没有这样做的包。 broom包不支持H2O模型 - 这很酷!也许这可能在未来发生。一旦有一种方法可以使用扫帚或类似的功能将模型输出“整理”到R data.frame中,那么xtable等将很好地工作。