Skip to content

Commit f0ece7d

Browse files
authored
Implement improved tinytable support (#1141)
1 parent e3a75e0 commit f0ece7d

29 files changed

+818
-1140
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Type: Package
22
Package: parameters
33
Title: Processing of Model Parameters
4-
Version: 0.27.0.1
4+
Version: 0.27.0.2
55
Authors@R:
66
c(person(given = "Daniel",
77
family = "Lüdecke",

NAMESPACE

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,12 @@ S3method(display,parameters_efa_summary)
128128
S3method(display,parameters_model)
129129
S3method(display,parameters_omega)
130130
S3method(display,parameters_omega_summary)
131+
S3method(display,parameters_p_function)
131132
S3method(display,parameters_pca)
132133
S3method(display,parameters_pca_summary)
133134
S3method(display,parameters_sem)
134135
S3method(display,parameters_simulate)
136+
S3method(display,parameters_standardized)
135137
S3method(dof_satterthwaite,lmerMod)
136138
S3method(equivalence_test,MixMod)
137139
S3method(equivalence_test,feis)
@@ -981,7 +983,6 @@ export(pool_parameters)
981983
export(principal_components)
982984
export(print_html)
983985
export(print_md)
984-
export(print_table)
985986
export(random_parameters)
986987
export(reduce_data)
987988
export(reduce_parameters)

NEWS.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# parameters (devel)
22

3+
## Breaking Changes
4+
5+
* The experimental `print_table()` function was removed. The aim of this function
6+
was to test the implementation of the `tinytable` backend for printing. Now,
7+
`tinytable` is fully supported by `insight::export_table()` and thereby also
8+
by the various `print()` resp. `display()` methods for model parameters.
9+
10+
## Changes
11+
12+
* All `print_html()` methods get an `engine` argument, to either use the `gt`
13+
package or the `tinytable` package for printing HTML tables. Since `tinytable`
14+
not only produces HTML tables, but rather different formats depending on the
15+
environment, `print_html()` may also generate a markdown table. Thus, the
16+
generic `display()` method can be used, too, which has a `format` argument that
17+
also supports `"tt"` for `tinytable`.
18+
319
## Bug fixes
420

521
* Fixed issue with models of class `selection` with multiple outcomes.

R/display.R

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@
33
#'
44
#' @description Prints tables (i.e. data frame) in different output formats.
55
#' `print_md()` is an alias for `display(format = "markdown")`, `print_html()`
6-
#' is an alias for `display(format = "html")`. `print_table()` is for specific
7-
#' use cases only, and currently only works for `compare_parameters()` objects.
6+
#' is an alias for `display(format = "html")`, and `print_html(engine = "tt")`
7+
#' is an alias for `display(format = "tt")`. The latter is a `tinytable` object,
8+
#' which is either printed as markdown or HTML table, depending on the environment.
89
#'
9-
#' @param x An object returned by [`model_parameters()`].
10-
#' @param object An object returned by [`model_parameters()`],[`simulate_parameters()`],
11-
#' [`equivalence_test()`] or [`principal_components()`].
10+
#' @param object An object returned by one of the package's function, for example
11+
#' [`model_parameters()`], [`simulate_parameters()`], [`equivalence_test()`] or
12+
#' [`principal_components()`].
1213
#' @param format String, indicating the output format. Can be `"markdown"`
13-
#' or `"html"`.
14+
#' `"html"`, or `"tt"`. `format = "tt"` creates a `tinytable` object, which is
15+
#' either printed as markdown or HTML table, depending on the environment. See
16+
#' [`insight::export_table()`] for details.
1417
#' @param align Only applies to HTML tables. May be one of `"left"`,
1518
#' `"right"` or `"center"`.
1619
#' @param digits,ci_digits,p_digits Number of digits for rounding or
@@ -27,17 +30,14 @@
2730
#' @param line_padding For HTML tables, the distance (in pixel) between lines.
2831
#' @param column_labels Labels of columns for HTML tables. If `NULL`, automatic
2932
#' column names are generated. See 'Examples'.
30-
#' @param theme String, indicating the table theme. Can be one of `"default"`,
31-
#' `"grid"`, `"striped"`, `"bootstrap"` or `"darklines"`.
3233
#' @inheritParams print.parameters_model
3334
#' @inheritParams insight::format_table
3435
#' @inheritParams insight::export_table
3536
#' @inheritParams compare_parameters
3637
#'
3738
#' @return If `format = "markdown"`, the return value will be a character
3839
#' vector in markdown-table format. If `format = "html"`, an object of
39-
#' class `gt_tbl`. For `print_table()`, an object of class `tinytable` is
40-
#' returned.
40+
#' class `gt_tbl`. If `format = "tt"`, an object of class `tinytable`.
4141
#'
4242
#' @details `display()` is useful when the table-output from functions,
4343
#' which is usually printed as formatted text-table to console, should
@@ -46,14 +46,6 @@
4646
#' [vignette](https://easystats.github.io/parameters/articles/model_parameters_formatting.html)
4747
#' for examples.
4848
#'
49-
#' `print_table()` is a special function for `compare_parameters()` objects,
50-
#' which prints the output as a formatted HTML table. It is still somewhat
51-
#' experimental, thus, only a fixed layout-style is available at the moment
52-
#' (columns for estimates, confidence intervals and p-values). However, it
53-
#' is possible to include other model components, like zero-inflation, or random
54-
#' effects in the table. See 'Examples'. An alternative is to set `engine = "tt"`
55-
#' in `print_html()` to use the _tinytable_ package for creating HTML tables.
56-
#'
5749
#' @seealso [print.parameters_model()] and [print.compare_parameters()]
5850
#'
5951
#' @examplesIf require("gt", quietly = TRUE)
@@ -81,6 +73,28 @@
8173
#' column_labels = c("Est. (95% CI)")
8274
#' )
8375
#' }
76+
#'
77+
#' @examplesIf all(insight::check_if_installed(c("glmmTMB", "lme4", "tinytable"), quietly = TRUE))
78+
#' \donttest{
79+
#' data(iris)
80+
#' data(Salamanders, package = "glmmTMB")
81+
#' m1 <- lm(Sepal.Length ~ Species * Petal.Length, data = iris)
82+
#' m2 <- lme4::lmer(
83+
#' Sepal.Length ~ Petal.Length + Petal.Width + (1 | Species),
84+
#' data = iris
85+
#' )
86+
#' m3 <- glmmTMB::glmmTMB(
87+
#' count ~ spp + mined + (1 | site),
88+
#' ziformula = ~mined,
89+
#' family = poisson(),
90+
#' data = Salamanders
91+
#' )
92+
#' out <- compare_parameters(m1, m2, m3, effects = "all", component = "all")
93+
#'
94+
#' display(out, format = "tt")
95+
#'
96+
#' display(out, select = "{estimate}|{ci}", format = "tt")
97+
#' }
8498
#' @export
8599
display.parameters_model <- function(object,
86100
format = "markdown",
@@ -123,7 +137,8 @@ display.parameters_model <- function(object,
123137
column_labels = column_labels,
124138
align = align,
125139
font_size = font_size,
126-
line_padding = line_padding
140+
line_padding = line_padding,
141+
engine = ifelse(format == "tt", "tt", "gt")
127142
)
128143
)
129144
do.call(print_html, c(fun_args, list(...)))
@@ -173,7 +188,8 @@ display.compare_parameters <- function(object,
173188
list(
174189
column_labels = column_labels,
175190
font_size = font_size,
176-
line_padding = line_padding
191+
line_padding = line_padding,
192+
engine = ifelse(format == "tt", "tt", "gt")
177193
)
178194
)
179195
do.call(print_html, c(fun_args, list(...)))
@@ -202,7 +218,8 @@ display.parameters_sem <- function(object,
202218
digits = digits,
203219
ci_digits = ci_digits,
204220
p_digits = p_digits,
205-
ci_brackets = ci_brackets
221+
ci_brackets = ci_brackets,
222+
engine = ifelse(format == "tt", "tt", "gt")
206223
)
207224

208225
if (format %in% c("html", "tt")) {
@@ -220,7 +237,7 @@ display.parameters_sem <- function(object,
220237
#' @export
221238
display.parameters_efa_summary <- function(object, format = "markdown", digits = 3, ...) {
222239
format <- insight::validate_argument(format, c("markdown", "html", "md", "tt"))
223-
fun_args <- list(x = object, digits = digits)
240+
fun_args <- list(x = object, digits = digits, engine = ifelse(format == "tt", "tt", "gt"))
224241

225242
if (format %in% c("html", "tt")) {
226243
do.call(print_html, c(fun_args, list(...)))
@@ -247,7 +264,8 @@ display.parameters_efa <- function(object, format = "markdown", digits = 2, sort
247264
digits = digits,
248265
sort = sort,
249266
threshold = threshold,
250-
labels = labels
267+
labels = labels,
268+
engine = ifelse(format == "tt", "tt", "gt")
251269
)
252270

253271
if (format %in% c("html", "tt")) {
@@ -272,3 +290,32 @@ display.parameters_omega <- display.parameters_efa
272290
display.equivalence_test_lm <- function(object, format = "markdown", digits = 2, ...) {
273291
print_md(x = object, digits = digits, ...)
274292
}
293+
294+
295+
# p_function ----------------------------
296+
297+
#' @export
298+
display.parameters_p_function <- function(object,
299+
format = "markdown",
300+
digits = 2,
301+
ci_width = "auto",
302+
ci_brackets = TRUE,
303+
pretty_names = TRUE,
304+
...) {
305+
format <- insight::validate_argument(format, c("markdown", "html", "md", "tt"))
306+
307+
fun_args <- list(
308+
x = object,
309+
digits = digits,
310+
ci_width = ci_width,
311+
ci_brackets = ci_brackets,
312+
pretty_names = pretty_names,
313+
engine = ifelse(format == "tt", "tt", "gt")
314+
)
315+
316+
if (format %in% c("html", "tt")) {
317+
do.call(print_html, c(fun_args, list(...)))
318+
} else {
319+
do.call(print_md, c(fun_args, list(...)))
320+
}
321+
}

R/format.R

Lines changed: 20 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -116,27 +116,13 @@ format.parameters_model <- function(x,
116116
x <- .format_ranef_parameters(x)
117117
}
118118

119-
# group parameters - this function find those parameters that should be
120-
# grouped, reorders parameters into groups and indents lines that belong
121-
# to one group, adding a header for each group
122-
if (!is.null(groups)) {
123-
x <- .parameter_groups(x, groups)
124-
}
125-
indent_groups <- attributes(x)$indent_groups
126-
indent_rows <- attributes(x)$indent_rows
127-
128119
# prepare output, to have in shape for printing. this function removes
129120
# empty columns, or selects only those columns that should be printed
130121
x <- .prepare_x_for_print(x, select, coef_name, s_value)
131122

132123
# check whether to split table by certain factors/columns (like component, response...)
133124
split_by <- .prepare_splitby_for_print(x)
134125

135-
# add p-stars, if we need this for style-argument
136-
if (!is.null(style) && grepl("{stars}", style, fixed = TRUE)) {
137-
x$p_stars <- insight::format_p(x[["p"]], stars = TRUE, stars_only = TRUE)
138-
}
139-
140126
# format everything now...
141127
if (split_components && !is.null(split_by) && length(split_by)) {
142128
# this function mainly sets the appropriate column names for each
@@ -158,6 +144,7 @@ format.parameters_model <- function(x,
158144
ci_brackets = ci_brackets,
159145
zap_small = zap_small,
160146
include_reference = include_reference,
147+
style = style,
161148
...
162149
)
163150
} else {
@@ -175,6 +162,7 @@ format.parameters_model <- function(x,
175162
coef_name = coef_name,
176163
zap_small = zap_small,
177164
include_reference = include_reference,
165+
style = style,
178166
...
179167
)
180168
}
@@ -189,33 +177,8 @@ format.parameters_model <- function(x,
189177
formatted_table$CI <- NULL
190178
}
191179

192-
# we also allow style-argument for model parameters. In this case, we need
193-
# some small preparation, namely, we need the p_stars column, and we need
194-
# to "split" the formatted table, because the glue-function needs the columns
195-
# without the parameters-column.
196-
if (!is.null(style)) {
197-
if (is.data.frame(formatted_table)) {
198-
formatted_table <- .style_formatted_table(
199-
formatted_table,
200-
style = style,
201-
format = format
202-
)
203-
} else {
204-
formatted_table[] <- lapply(
205-
formatted_table,
206-
.style_formatted_table,
207-
style = style,
208-
format = format
209-
)
210-
}
211-
}
212-
213-
if (!is.null(indent_rows)) {
214-
attr(formatted_table, "indent_rows") <- indent_rows
215-
attr(formatted_table, "indent_groups") <- NULL
216-
} else if (!is.null(indent_groups)) {
217-
attr(formatted_table, "indent_groups") <- indent_groups
218-
}
180+
# information about indention / row groups
181+
attr(formatted_table, "indent_rows") <- groups
219182

220183
# vertical layout possible, if these have just one row
221184
if (identical(list(...)$layout, "vertical")) {
@@ -375,8 +338,8 @@ format.compare_parameters <- function(x,
375338
}
376339
out$Parameter[out$Parameter == "SD (Observations: Residual)"] <- "SD (Residual)"
377340
}
341+
attributes(cols)$coef_name <- colnames(cols)[coef_column]
378342
# save p-stars in extra column
379-
cols$p_stars <- insight::format_p(cols$p, stars = TRUE, stars_only = TRUE)
380343
cols <- insight::format_table(
381344
cols,
382345
digits = digits,
@@ -385,9 +348,20 @@ format.compare_parameters <- function(x,
385348
ci_digits = ci_digits,
386349
p_digits = p_digits,
387350
zap_small = zap_small,
351+
select = select,
388352
...
389353
)
390-
out <- cbind(out, .format_output_style(cols, style = select, format, i))
354+
355+
# add modelname to column names; for single column layout per model, we just
356+
# need the column name. If the layout contains more than one column per model,
357+
# add modelname in parenthesis.
358+
if (ncol(cols) > 1) {
359+
colnames(cols) <- paste0(colnames(cols), " (", i, ")")
360+
} else {
361+
colnames(cols) <- i
362+
}
363+
364+
out <- cbind(out, cols)
391365
}
392366

393367
# remove group column
@@ -399,15 +373,6 @@ format.compare_parameters <- function(x,
399373
out <- datawizard::data_arrange(out, c("Effects", "Component"))
400374
}
401375

402-
# group parameters - this function find those parameters that should be
403-
# grouped, reorders parameters into groups and indents lines that belong
404-
# to one group, adding a header for each group
405-
if (!is.null(groups) && !identical(engine, "tt")) {
406-
out <- .parameter_groups(out, groups)
407-
}
408-
indent_groups <- attributes(x)$indent_groups
409-
indent_rows <- attributes(x)$indent_rows
410-
411376
# check whether to split table by certain factors/columns (like component, response...)
412377
split_by <- split_column <- .prepare_splitby_for_print(x)
413378

@@ -469,6 +434,9 @@ format.compare_parameters <- function(x,
469434
formatted_table <- .add_obs_row(formatted_table, parameters_attributes, style = select)
470435
}
471436

437+
# information about indention / row groups
438+
attr(formatted_table, "indent_rows") <- groups
439+
472440
formatted_table
473441
}
474442

@@ -510,35 +478,6 @@ format.parameters_sem <- function(x,
510478
}
511479

512480

513-
# helper ---------------------
514-
515-
.style_formatted_table <- function(formtab, style, format) {
516-
additional_columns <- intersect(c("Effects", "Group", "Component"), colnames(formtab))
517-
if (length(additional_columns)) {
518-
additional_columns <- formtab[additional_columns]
519-
}
520-
# define column names in case the glue-pattern has multiple columns.
521-
if (grepl("|", style, fixed = TRUE)) {
522-
cn <- NULL
523-
} else {
524-
cn <- .style_pattern_to_name(style)
525-
}
526-
formtab <- cbind(
527-
formtab[1],
528-
.format_output_style(
529-
formtab[2:ncol(formtab)],
530-
style = style,
531-
format = format,
532-
modelname = cn
533-
)
534-
)
535-
if (!insight::is_empty_object(additional_columns)) {
536-
formtab <- cbind(formtab, additional_columns)
537-
}
538-
formtab
539-
}
540-
541-
542481
# footer functions ------------------
543482

544483
.format_footer <- function(x,

0 commit comments

Comments
 (0)