texreg
包作者在这里。texreg
基于通用功能,这意味着任何用户都可以添加自定义功能extract
任意模型的方法并使它们与texreg
。下面我将引导您完成这个过程。我希望这个详细的阐述能够帮助过去提出过类似问题的其他人设计自己的解决方案texreg
扩展。
另请参阅第 6 节2013年《统计软件杂志》上的论文 http://dx.doi.org/10.18637/jss.v055.i08再举个例子。不过,首先我将描述如何texreg
建筑的工作更普遍的是让你了解什么是可能的。
texreg
和通用的extract
功能
共有三个功能:texreg
(对于 LaTeX 输出),htmlreg
(对于HTML输出,在大多数使用场景下也可以通过Word或Markdown解释),以及screenreg
(用于控制台中的 ASCII 文本输出)。这三个函数用于将一些清理后的信息(系数、标准误差、置信区间、p 值、拟合优度统计、模型标签等)转换为各自的输出格式。这并不完美,甚至可以更加灵活,但我认为目前它有很多关于定制的论据,包括诸如booktabs
and dcolumn
支持。因此,最大的挑战是首先获得清理后的模型信息。
这是通过提供一个来完成的texreg
反对这三个功能中的任何一个。 Atexreg
object 只是系数等的容器,并且使用 S4 类正式定义。创建一个texreg
对象,您可以使用构造函数createTexreg
(如帮助页面上所述),它接受所有不同的信息作为参数,例如标准错误等。或者(更好)您可以使用extract
函数从某个估计模型中提取这些信息并返回texreg
与这三个函数中的任何一个一起使用的对象。通常执行此操作的方法是将多个模型的列表移交给texreg
or screenreg
等等函数,这个函数内部会调用extract
创造texreg
对象,然后处理来自这些对象的信息。
但是,仅保存调用的输出同样有效extract
函数到一个对象,可能会操纵这个texreg
对象,然后调用texreg
作用于被操纵的对象,将其显示为表格。这允许在调整结果时具有一定的灵活性。
早些时候,我提到该包使用通用函数。这意味着extract
函数是通用的,因为您可以为其注册适用于任意模型类的方法。例如,如果extract
函数不知道如何处理h2o
对象以及如何从这样的对象中提取相关信息,您可以编写一个方法来执行此操作并将其注册到extract
功能。下面,我将逐步引导您完成这一过程,希望人们能够从这个详细的阐述中学习并开始编写自己的扩展。 (注意:如果有人开发了一个有用的方法,请给我发电子邮件,我可以将其包含在下一个texreg
发布。)还值得指出的是,该包的源文件包含 70 多个示例extract
可以用作模板的方法。这些示例存储在文件中R/extract.R
.
识别类标签并设置extract
method
第一步是识别对象的类名。在你的例子中,class(model.output.1)
返回以下类标签:“H2OBinomialModel”和“h2o”。第一个标签是更具体的标签,第二个标签是更通用的标签。我摔倒h2o
模型对象的结构类似,因此编写扩展是有意义的h2o
对象,然后在方法内决定如何继续处理特定模型。由于我对此几乎一无所知h2o
包,我更喜欢从更具体的开始extract
方法用于H2OBinomialModel
在这种情况下的对象。如果我们愿意的话,可以稍后进行调整。
extract
方法的结构如下:您编写一个名为extract.xyz
(用类标签替换“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)
}
请注意,函数定义还包含...
参数,可用于应传递给函数内的函数调用的自定义参数extract
method.
另请注意,函数定义主体中的第一行将模型的摘要保存在名为s
。这通常很有用,因为许多包编写者决定将一些信息存储在摘要中的更简单版本中,因此通常应该将模型及其摘要视为有用的信息源。在某些情况下,可能需要查看相应包中摘要方法的实际定义,以了解当摘要页面上显示的信息是如何计算的。summary
调用命令是因为并非所有summary
方法存储显示在中的不同元素summary
object.
在其中找到正确的信息H2OBinomialModel
object
下一步是检查对象并找到应在最终表中显示的所有详细信息。通过查看输出model.output.1
,我猜下面的部分应该构成表底部的GOF块:
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
在许多情况下,摘要包含相关信息,但这里打印模型会产生我们需要的信息。我们需要将所有这些都放在model.output.1
对象(或其摘要,如果适用)。为此,有几个有用的命令。其中有str(model.output.1)
, names(summary(model.output.1))
和类似的命令。
让我们从系数块开始。呼唤str(model)
显示有一个名为model
在 S4 对象中。我们可以通过调用来查看其内容model.output.1@model
。结果是一个包含多个命名元素的列表,其中coefficients_table
。所以我们可以通过调用访问系数表model.output.1@model$coefficients_table
。结果是一个数据框,我们可以使用以下命令访问其中的列$
操作员。特别是,我们需要名称和系数。这里有两种类型的系数,标准化和非标准化,我们可以稍后在 extract 方法中添加一个参数,让用户决定他或她想要什么。以下是我们提取系数及其标签的方法:
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
据我所知,对象中没有存储标准错误或 p 值。如果我们愿意的话,我们可以编写一些额外的代码来计算它们,但在这里我们将重点关注作为模型输出的一部分轻松提供的内容。
重要的是我们不应该覆盖任何现有的函数名称R
, 例如names
or coef
。虽然这样做在技术上应该可行,因为代码稍后在函数内执行,但这很容易导致尝试时出现混乱,因此您应该最好避免这种情况。
接下来,我们需要找到拟合优度统计量。通过检查输出str(model.output.1)
仔细观察,我们发现拟合优度统计数据包含在下面的几个槽中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 (AIC(model)
), BIC (BIC(model)
), 偏差 (deviance(model)
),或对数似然(logLik(model)[[1]]
)。所以这些是你可能想首先尝试的事情;但是h2o
包似乎没有提供这样方便的方法。
将信息添加到extract.H2OBinomialModel
功能
现在我们已经找到了所需的所有信息,我们可以将它们添加到extract.H2OBinomialModel
我们上面定义的函数。
然而,我们想让用户决定他或她更喜欢原始系数还是标准化系数,并且我们想让用户决定应该报告哪些拟合优度统计数据,因此我们在函数头中添加了各种逻辑参数然后在函数内使用 if 条件来检查我们是否应该将相应的统计数据嵌入到结果中texreg
object.
我们还删除了该行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)
}
对于拟合优度块,您可以看到我首先创建了空向量,然后用其他统计数据填充它们,前提是用户使用相应的参数打开了相应的统计数据。
The gof.decimal
逻辑向量指示每个 GOF 统计量是否有小数位(TRUE
) 或不 (FALSE
,例如观察次数)。
最后,新函数需要注册为通用方法extract
功能。这是使用一个简单的命令完成的:
setMethod("extract", signature = className("H2OBinomialModel", "h2o"),
definition = extract.H2OBinomialModel)
这里,第一个参数className
是类标签,第二个是定义该类的包。
总而言之,编写自定义扩展只需要做两件事:1) 编写提取方法,2) 注册该方法。也就是说,该代码可以在运行时执行,而不必插入任何包中。
不过,为了您的方便,我添加了H2OBinomialModel
方法texreg
版本 1.36.13,可在 CRAN 上获取。
请注意,此处提供的解决方案不适用于任何早期版本texreg
因为以前的版本无法处理既没有标准误差也没有置信区间的模型。在我看来,这是一个相当专业的设置,我还没有遇到过一个只提供估计而没有任何不确定性措施的软件包。我现在已经解决了这个问题texreg
.
尝试新的extract
method
一旦函数定义和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
======================================
The custom.note = ""
争论在这里是有道理的,因为我们不需要显着性图例,因为模型不报告任何不确定性度量。
还可以抑制某些 GOF 测量和/或使用标准化系数:
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
======================================
其他可以使用的插槽createTexreg
The createTexreg
构造函数在任何内部调用extract
方法。上面的示例显示了一些简单的信息。除了示例中包含的详细信息之外,还可以使用以下插槽texreg
对象:
- se:标准错误
- pvalues:p 值
- ci.low:置信区间的下限
- ci.up:置信区间的上限
- model.name:当前模型的标题
请注意,应使用置信区间或标准误差和 p 值,而不是同时使用两者。
操纵texreg
objects
除了将模型移交给screenreg
, texreg
, or htmlreg
直接使用函数,可以将提取的信息保存到texreg
首先对象并在显示或保存表之前对其进行操作。附加值是,即使对表进行复杂的更改也可以轻松应用这种方式。例如,可以重命名系数或 GOF 统计数据、添加新行、重命名模型、修改值或更改系数或 GOF 统计数据的顺序。以下是您可以执行此操作的方法:首先,您调用extract
功能将信息保存到texreg
object:
tr <- extract(model.output.1)
您可以显示以下内容texreg
只需调用对象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)
现在您可以以任意方式操作该对象,例如添加 GOF 统计数据:
[email protected] /cdn-cgi/l/email-protection <- c([email protected] /cdn-cgi/l/email-protection, "new statistic")
tr@gof <- c(tr@gof, 12)
[email protected] /cdn-cgi/l/email-protection <- c([email protected] /cdn-cgi/l/email-protection, FALSE)
或者您可以更改系数的顺序:
[email protected] /cdn-cgi/l/email-protection <- tr@coef.names[c(4, 1, 2, 3)]
tr@coef <- tr@coef[c(4, 1, 2, 3)]
完成操作后,您可以移交texreg
例如,当您调用时,对象而不是原始模型,screenreg
:
screenreg(list(tr, model.output.2), custom.note = "")
新结果将如下所示:
======================================
Model 1 Model 2
--------------------------------------
PSA 0.05 0.05
Intercept -1.84 -1.11
RACE -0.63 -0.62
DCAPS 1.31 1.31
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
new statistic 12
======================================
TL;DR
texreg
可由用户定制。只需编写一个像上面所示的提取方法并使用setMethods
称呼。我已经包括了H2OBinomialModel
方法中的latest texreg version https://github.com/leifeld/texreg1.36.13,以及使用没有标准错误的模型(例如这个)的错误修复。