Печать «хороших» таблиц для моделей h2o в R

Существует несколько пакетов для R которые помогают печатать «красивые» таблицы (LaTeX / HTML / TEXT) из выходных данных статистических моделей и легко сравнивать результаты альтернативных спецификаций модели.

Некоторые из этих пакетов apsrtable , xtable , memisc , texreg , outreg и outreg (примеры см. Здесь: https://www.r-statistics.com/2013/01/stargazer-package-for-beautiful-latex-tables -from-r-statistics-models-output / ).

Есть ли сопоставимый пакет R , который поддерживает модели пакета h2o ?

Вот пример двух простых моделей GLM с h2o которые мне нравится печатать рядом друг с другом как «красивые» таблицы.

 # 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) 

Так будет выглядеть обычный объект GLM с использованием screenreg() из пакета texreg :

 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)) 

введите описание изображения здесь

texreg автор пакета здесь. texreg основан на общих функциях, что означает, что любой пользователь может добавлять собственные методы extract для произвольных моделей и заставить их работать с texreg . Я проведу вас через это ниже. Я надеюсь, что это подробное изложение поможет другим людям, которые задавали подобные вопросы в прошлом, разработать свои собственные расширения texreg .

См. Также раздел 6 в документе 2013 года в журнале статистического программного обеспечения для другого примера. Во-первых, однако, я опишу, как архитектура texreg работает в целом, чтобы дать вам представление о том, что возможно.

texreg и общая функция extract

Существуют три функции: texreg (для выхода LaTeX), htmlreg (для вывода HTML, который также может быть интерпретирован Word или Markdown в большинстве сценариев использования) и screenreg (для вывода текста ASCII в консоли). Эти три функции служат для преобразования некоторой очищенной информации (коэффициенты, стандартные ошибки, доверительные интервалы, значения p, статистика пригодности, метки модели и т. Д.) В соответствующие выходные форматы. Это не идеально и может быть еще более гибким, но я думаю, что на данный момент у него есть немало аргументов для настройки, включая такие вещи, как booktabs и поддержка dcolumn . Поэтому большая проблема состоит в том, чтобы в первую очередь получить очищенную информацию о модели.

Это делается путем предоставления объекта texreg любой из этих трех функций. Объект texreg – это просто контейнер для коэффициентов и т. Д. И формально определяется с использованием classа S4. Чтобы создать объект texreg , вы можете либо использовать конструкторную функцию createTexreg (как createTexreg на страницах справки), которая принимает все различные части информации в качестве аргументов, такие как стандартные ошибки и т. Д. Или (лучше) вы можете использовать extract чтобы извлечь эти части информации из некоторой оценочной модели и вернуть объект texreg для использования с любой из трех функций. Как обычно вы делаете это, просто texreg список нескольких моделей функции texreg или screenreg и т. Д., И эта функция будет внутренне вызывать extract для создания объектов texreg а затем обрабатывать информацию с этих объектов.

Тем не менее, в равной степени справедливо просто сохранять вывод вызова функции extract для объекта, возможно, манипулировать этим объектом texreg , а затем вызывать функцию texreg на управляемом объекте для отображения его в виде таблицы. Это дает некоторую гибкость в настройке результатов.

Ранее я упомянул, что пакет использует общие функции. Это означает, что функция extract является общей в том смысле, что вы можете регистрировать методы для нее, которые работают с произвольными classами моделей. Например, если функция extract не знает, как обрабатывать объекты h2o и как извлекать соответствующую информацию из такого объекта, вы можете просто написать способ для этого и зарегистрировать ее с помощью функции extract . Ниже я буду проходить через это шаг за шагом в надежде, что люди извлекут уроки из этого подробного изложения и начнут писать собственные расширения. (Примечание: если кто-то разработает полезный метод, напишите мне по электронной почте, и я могу включить его в следующий выпуск texreg .) Также стоит указать, что исходные файлы пакета содержат более 70 примеров методов extract которые вы могут использоваться в качестве шаблонов. Эти примеры хранятся в файле R/extract.R .

Идентификация метки classа и настройка метода extract

Первый шаг – идентифицировать имя classа объекта. В вашем примере class(model.output.1) возвращает следующие метки classов: «H2OBinomialModel» и «h2o». Первый ярлык является более конкретным, а второй ярлык является более общим. Если все объекты модели h2o структурированы аналогичным образом, имеет смысл написать расширение для объектов h2o а затем решить в рамках метода, как перейти к конкретной модели. Поскольку я практически ничего не знаю о пакете h2o , я предпочитаю начать с более конкретного метода extract для объектов H2OBinomialModel в этом случае. Он может быть скорректирован позже, если мы хотим это сделать.

методы extract структурированы следующим образом: вы пишете функцию extract.xyz (замените «xyz» на метку classа), по крайней мере, один аргумент, называемый model , который принимает объект модели (например, model.output.1 в вашем примере ), поместите в тело какой-то код, который извлекает соответствующую информацию из объекта model , создает объект texreg с createTexreg конструктора 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 .

Также обратите внимание, что первая строка в теле определения функции сохраняет сводку модели в объекте с именем s . Это часто полезно, потому что многие составители пакетов решают сохранить некоторую информацию в более простой версии в сводке, поэтому обычно следует рассматривать как модель, так и ее резюме как полезные источники информации. В некоторых случаях, возможно, придется посмотреть на фактическое определение метода суммирования в соответствующем пакете, чтобы узнать, как части информации, отображаемые на итоговой странице, вычисляются при вызове команды summary поскольку не все методы summary хранят разные элементы, отображаемые в summary объекте.

Поиск нужной информации в объекте H2OBinomialModel

Следующий шаг - изучить объект и найти все детали, которые должны отображаться в итоговой таблице. Посмотрев на вывод 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) показывает, что в объекте S4 есть слот, называемый model . Мы можем посмотреть его содержимое, вызвав [email protected] . Результатом является список с несколькими именованными элементами, в том числе coefficients_table . Таким образом, мы можем получить доступ к таблице коэффициентов, вызывая [email protected]$coefficients_table . Результатом является кадр данных, столбцы которого мы можем получить, используя оператор $ . В частности, нам нужны имена и коэффициенты. Здесь есть два типа коэффициентов, стандартизованные и нестандартные, и мы можем добавить аргумент в наш метод извлечения позже, чтобы позволить пользователю решить, что он или она хочет. Вот как мы извлекаем коэффициенты и их метки:

 coefnames <- [email protected]$coefficients_table$names coefs <- [email protected]$coefficients_table$coefficients coefs.std <- [email protected]$coefficients_table$standardized_coefficients 

Насколько я вижу, в объекте нет стандартных ошибок или значений p. Мы могли бы написать некоторый дополнительный код, чтобы вычислить их, если мы хотим это сделать, но здесь мы сосредоточимся на вещах, которые легко предоставляются как часть вывода модели.

Важно, чтобы мы не переписывали существующие имена функций в R , такие как names или coef . В то время как это должно технически работать, потому что код выполняется в функции позже, это может легко привести к путанице при попытке выяснить, так что вам следует избегать этого.

Затем нам нужно найти статистику о пригодности. Изучая вывод str(model.output.1) тщательно, мы видим, что статистические данные о хорошей пригодности содержатся в нескольких слотах в [email protected]$trai[email protected] . Давайте сохраним их на некоторые объекты, к которым легче получить доступ:

 mse <- [email protected][email protected]$MSE r2 <- [email protected][email protected]$r2 logloss <- [email protected][email protected]$logloss mpce <- [email protected][email protected]$mean_per_class_error auc <- [email protected][email protected]$AUC gini <- [email protected][email protected]$Gini nulldev <- [email protected][email protected]$null_deviance resdev <- [email protected][email protected]$residual_deviance aic <- [email protected][email protected]$AIC 

В некоторых случаях, но не здесь, автор пакета пишет методы для общих функций, которые могут быть использованы для извлечения некоторой общей информации, такой как количество наблюдений ( nobs(model) ), AIC ( AIC(model) ), BIC ( BIC(model) ), отклонение ( deviance(model) ) или логарифмическая вероятность ( logLik(model)[[1]] ). Итак, это то, что вы можете попробовать первым; но пакет h2o , похоже, не предлагает таких методов удобства.

Добавление информации в функцию extract.H2OBinomialModel

Теперь, когда мы располагаем всеми необходимыми сведениями, мы можем добавить их в функцию extract.H2OBinomialModel мы определили выше.

Однако мы хотели бы, чтобы пользователь решил, предпочитает ли он сырые или стандартизованные коэффициенты, и мы хотели бы, чтобы пользователь решил, какие статистические данные о пригодности должны быть представлены, поэтому мы добавляем различные логические аргументы в заголовок функции а затем использовать if-conditions внутри функции, чтобы проверить, следует ли встраивать соответствующую статистику в результирующий объект 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 <- [email protected]$coefficients_table$names if (standardized == TRUE) { coefs <- [email protected]$coefficients_table$standardized_coefficients } else { coefs <- [email protected]$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 <- [email protected][email protected]$MSE gof <- c(gof, mse) gof.names <- c(gof.names, "MSE") gof.decimal <- c(gof.decimal, TRUE) } if (include.rsquared == TRUE) { r2 <- [email protected]$training_met[email protected]$r2 gof <- c(gof, r2) gof.names <- c(gof.names, "R^2") gof.decimal <- c(gof.decimal, TRUE) } if (include.logloss == TRUE) { logloss <- [email protected][email protected]$logloss gof <- c(gof, logloss) gof.names <- c(gof.names, "LogLoss") gof.decimal <- c(gof.decimal, TRUE) } if (include.meanerror == TRUE) { mpce <- [email protected][email protected]$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 <- [email protected][email protected]$AUC gof <- c(gof, auc) gof.names <- c(gof.names, "AUC") gof.decimal <- c(gof.decimal, TRUE) } if (include.gini == TRUE) { gini <- [email protected][email protected]$Gini gof <- c(gof, gini) gof.names <- c(gof.names, "Gini") gof.decimal <- c(gof.decimal, TRUE) } if (include.deviance == TRUE) { nulldev <- [email protected][email protected]$null_deviance resdev <- [email protected][email protected]$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 <- [email protected][email protected]$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) } 

Для блока goodness-of-fit вы можете видеть, что я сначала создал пустые векторы, а затем добавил их дополнительную статистику при условии, что соответствующая статистика была включена пользователем с использованием соответствующего аргумента.

Логический вектор gof.decimal указывает для каждой статистики GOF, имеет ли она десятичные знаки ( TRUE ) или нет ( FALSE , например, в числе наблюдений).

Наконец, новая функция должна быть зарегистрирована как метод для общей функции extract . Это делается с помощью простой команды:

 setMethod("extract", signature = className("H2OBinomialModel", "h2o"), definition = extract.H2OBinomialModel) 

Здесь первым аргументом className является метка classа, а вторая - это пакет, в котором определяется class.

Подводя итог, единственные две вещи, которые необходимо выполнить для написания пользовательского расширения: 1) написание метода извлечения и 2) регистрация метода. То есть, этот код можно выполнить во время выполнения и не нужно вставлять в какой-либо пакет.

Однако для вашего удобства я добавил метод texreg версию texreg версии 1.36.13, доступную на CRAN.

Обратите внимание, что представленное здесь решение не работает с предыдущей версией texreg поскольку предыдущие версии не могли иметь дело с моделями, которые не имели ни стандартных ошибок, ни доверительных интервалов. По-моему, это довольно специализированная установка, и я не сталкивался с пакетом, который просто дает оценки без каких-либо мер неопределенности. Теперь я исправил это в texreg .

Попробуйте новый метод extract

После определения функции и команды 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 ====================================== 

Другие слоты, которые можно использовать с createTexreg

Функция конструктора createTexreg вызывается внутри любого метода extract . В приведенном выше примере показаны некоторые простые fragmentы информации. Помимо деталей, содержащихся в этом примере, в объектах texreg доступны следующие слоты:

  • se: стандартные ошибки
  • pvalues: значения p
  • ci.low: нижняя граница доверительного интервала
  • ci.up: верхняя граница доверительного интервала
  • model.name: название текущей модели

Обратите внимание, что должны использоваться либо доверительные интервалы, либо стандартные ошибки, и значения p, а не оба.

Манипулирование объектами texreg

Помимо непосредственного передачи моделей на функции screenreg , texreg или htmlreg , можно сначала сохранить извлеченную информацию в объект texreg и обработать ее до того, как таблица будет отображаться или сохраняться. Добавленная ценность заключается в том, что даже сложные изменения в таблице легко применять таким образом. Например, можно переименовать коэффициенты или статистику GOF, добавить новые строки, переименовать модель, изменить значения или изменить порядок коэффициентов или статистику GOF. Вот как вы можете это сделать: во-первых, вы вызываете функцию extract для сохранения информации в объект texreg :

 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 [email protected] coef.names : chr [1:4] "Intercept" "RACE" "DCAPS" "PSA" [email protected] coef : num [1:4] -1.8352 -0.6252 1.3144 0.0469 [email protected] se : num(0) [email protected] pvalues : num(0) [email protected] ci.low : num(0) [email protected] ci.up : num(0) [email protected] gof.names : chr [1:9] "MSE" "R^2" "LogLoss" "Mean Per-Class Error" ... [email protected] gof : num [1:9] 0.203 0.156 0.592 0.361 0.719 ... [email protected] gof.decimal: logi [1:9] TRUE TRUE TRUE TRUE TRUE TRUE ... [email protected] model.name : chr(0) 

Теперь вы можете просто манипулировать этим объектом произвольным образом, например, добавить статистику GOF:

 [email protected] <- c([email protected], "new statistic") [email protected] <- c([email protected], 12) [email protected] <- c([email protected], FALSE) 

Или вы можете изменить порядок коэффициентов:

 [email protected] <- [email protected][c(4, 1, 2, 3)] [email protected] <- [email protected][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 в последнюю версию texreg версии 1.36.13 вместе с исправлением ошибок для использования моделей без стандартных ошибок (таких как этот).

вы можете использовать пакет R xtable с H2OTable h2o (или knitr, если вы преобразуете H2OTable в H2OFrame, используя as.h2o(your_H2OTable) ), если вы извлечете их из вывода модели.

например, чтобы создать красивую таблицу из коэффициентов модели, вам нужно будет сначала извлечь таблицу коэффициентов с помощью [email protected]$coefficients_table , тогда вы можете использовать xxtable: xtable([email protected]$coefficients_table) для печати латексный код.

для боковых представлений есть несколько сообщений о том, как это сделать в knitr или xtable , или xtable и sweave

Нет, в данный момент нет пакета. В комплекте с метлой еще не поддерживаются модели H2O – это было бы круто! Возможно, это может произойти в будущем. Когда есть способ «вывести» модельный вывод в R-файл данных, используя метлу или аналогичную функциональность, то xtable и т. Д. Будут работать хорошо.

Interesting Posts

Значение аргумента epsilon для assertEquals для двойных значений

MVC3 Razor DropDownListFor Enums

Класс JavaLaunchHelper реализован в обоих. Один из двух будет использован. Какой из них не определен

почему math.max () возвращает NaN с массивом целых чисел?

Google-Chrome: сохранить как полную веб-страницу

Windows с полным контролем для всех для всего

Рассмотрим определение компонента типа «package» в вашей конфигурации

Как протестировать Facebook Connect Locally

Java обращает значение int без использования массива

Решение «Не удалось вызвать назначенный инициализатор в classе NSManagedObject»

Почему Windows 7 иногда забывает отключить мой дисплей после X минут, даже если настройки мощности специально настроены таким образом?

Имя пользователя ASP.Net для электронной почты

Как я могу создать пользователя с доступом только для чтения ко всем файлам? (Т.е. root без разрешения на запись)

Производительность HashSet.contains

Какая папка App_Data используется в Visual Studio?

Давайте будем гением компьютера.