Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Issue #799 #800

Merged
merged 7 commits into from
Aug 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Description: Create beautiful and customizable tables to summarize several
RTF, JPG, or PNG. Tables can easily be embedded in 'Rmarkdown' or 'knitr'
dynamic documents. Details can be found in Arel-Bundock (2022)
<doi:10.18637/jss.v103.i01>.
Version: 2.1.1.5
Version: 2.1.1.6
Authors@R: c(person("Vincent", "Arel-Bundock",
email = "[email protected]",
role = c("aut", "cre"),
Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
* `kableExtra` escapes footnotes in HTML when `output="kableExtra")`. Thanks to @dmurdoch and @michaelherndon97 for report #793.
* New `fmt_equivalence()` function to implement the rounding suggestion of Astier & Wolak (2024). Thanks to Nicolas Astier for code prototype.

Bugs:

* `datasummary_*()` functions can be called as arguments in another `datasummary_*()` arguments, like `add_columns`. Thanks to @mronkko for report #799

## 2.1.1

* Documentation improvements
Expand Down
10 changes: 8 additions & 2 deletions R/datasummary.R
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,10 @@ datasummary <- function(formula,
))
}

sanitize_output(output) # before sanitize_escape
tmp <- sanitize_output(output) # early
output_format <- tmp$output_format
output_factory <- tmp$output_factory
output_file <- tmp$output_file
sanitize_escape(escape) # after sanitize_output
sanity_align(align)

Expand Down Expand Up @@ -237,10 +240,13 @@ datasummary <- function(formula,
add_columns = add_columns,
add_rows = add_rows,
escape = escape,
output_factory = output_factory,
output_format = output_format,
output_file = output_file,
...)

# invisible return
if (!is.null(settings_get("output_file")) ||
if (!is.null(output_file) ||
output == "jupyter" ||
(output == "default" && settings_equal("output_default", "jupyter"))) {
if (!isTRUE(list(...)[["internal_call"]])) settings_rm()
Expand Down
17 changes: 12 additions & 5 deletions R/datasummary_balance.R
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,15 @@ datasummary_balance <- function(formula,
settings_init(settings = list("function_called" = "datasummary_balance"))

## sanity checks
sanitize_output(output) # before sanitize_escape
tmp <- sanitize_output(output) # before sanitize_escape
output_format <- tmp$output_format
output_factory <- tmp$output_factory
output_file <- tmp$output_file

# this is going to be detected by fmt_mathmode() when we call
# datasummary(output="dataframe") so we can get siunitx formatting even in
# internal calls.
settings_set("output_format_ultimate", settings_get("output_format"))
settings_set("output_format_ultimate", output_format)

sanity_align(align)
sanitize_escape(escape) # after sanitize_output
Expand Down Expand Up @@ -156,7 +160,7 @@ datasummary_balance <- function(formula,

## datasummary(output="dataframe") changes the output format
sanitize_output(output)
settings_set("output_format_ultimate", settings_get("output_format"))
settings_set("output_format_ultimate", output_format)

## enforce 2-column stub, even when there is only one factor
idx <- grep("bad_factor_for_stub", tab_fac[[1]])
Expand Down Expand Up @@ -203,7 +207,7 @@ datasummary_balance <- function(formula,

## datasummary(output="dataframe") changes the output format
sanitize_output(output)
settings_set("output_format_ultimate", settings_get("output_format"))
settings_set("output_format_ultimate", output_format)
}

## combine
Expand Down Expand Up @@ -287,10 +291,13 @@ datasummary_balance <- function(formula,
add_columns = add_columns,
title = title,
escape = escape,
output_factory = output_factory,
output_format = output_format,
output_file = output_file,
...)

# invisible return
if (!is.null(settings_get("output_file")) ||
if (!is.null(output_file) ||
output == "jupyter" ||
(output == "default" && settings_equal("output_default", "jupyter"))) {
settings_rm()
Expand Down
10 changes: 8 additions & 2 deletions R/datasummary_correlation.R
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,10 @@ datasummary_correlation <- function(data,
))

# sanity checks
sanitize_output(output) # before sanitize_escape
tmp <- sanitize_output(output) # before sanitize_escape
output_format <- tmp$output_format
output_factory <- tmp$output_factory
output_file <- tmp$output_file
sanitize_escape(escape) # after sanitize_output
sanity_add_columns(add_columns)
sanity_align(align)
Expand Down Expand Up @@ -244,10 +247,13 @@ datasummary_correlation <- function(data,
notes = notes,
title = title,
escape = escape,
output_factory = output_factory,
output_format = output_format,
output_file = output_file,
...)

# invisible return
if (!is.null(settings_get("output_file")) ||
if (!is.null(output_file) ||
output == "jupyter" ||
(output == "default" && settings_equal("output_default", "jupyter"))) {
settings_rm()
Expand Down
7 changes: 5 additions & 2 deletions R/datasummary_crosstab.R
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ datasummary_crosstab <- function(formula,


# argument checking
sanitize_output(output) # before sanitize_escape
tmp <- sanitize_output(output) # before sanitize_escape
output_format <- tmp$output_format
output_factory <- tmp$output_factory
output_file <- tmp$output_file
sanitize_escape(escape) # after sanitize_output

checkmate::assert_formula(formula)
Expand Down Expand Up @@ -182,7 +185,7 @@ Note that the `datasummary()` function supports the `=` sign and the `Heading()`
escape = escape,
...)

if (!is.null(settings_get("output_file"))) {
if (!is.null(output_file)) {
settings_rm()
return(invisible(out))
} else {
Expand Down
8 changes: 7 additions & 1 deletion R/datasummary_df.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ datasummary_df <- function(data,

settings_init(settings = list("function_called" = "datasummary_df"))

sanitize_output(output) # before sanitize_escape
tmp <- sanitize_output(output) # before sanitize_escape
output_format <- tmp$output_format
output_factory <- tmp$output_factory
output_file <- tmp$output_file
sanitize_escape(escape) # after sanitize_output
sanity_align(align)

Expand All @@ -39,6 +42,9 @@ datasummary_df <- function(data,
escape = escape,
add_rows = add_rows,
add_columns = add_columns,
output_factory = output_factory,
output_format = output_format,
output_file = output_file,
...)

settings_rm()
Expand Down
13 changes: 8 additions & 5 deletions R/datasummary_skim.R
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ datasummary_skim <- function(data,

## settings
settings_init(settings = list("function_called" = "datasummary_skim"))
sanitize_output(output) # before sanitize_escape
tmp <- sanitize_output(output) # before sanitize_escape
output_format <- tmp$output_format
output_factory <- tmp$output_factory
output_file <- tmp$output_file
sanitize_escape(escape) # after sanitize_output
sanity_align(align)
checkmate::assert_list(fun_numeric, min.len = 1, names = "unique")
Expand Down Expand Up @@ -99,7 +102,7 @@ datasummary_skim <- function(data,
out <- tinytable::rbind2(a, b, use_names = FALSE)
out <- tinytable::format_tt(out, replace = "")
out <- tinytable::style_tt(out, i = nrow(a) + 1, line = "t", line_size = .3)
if (settings_equal("output_format", "html")) {
if (identical(output_format, "html")) {
out <- tinytable::style_tt(out, i = nrow(a) + 1, bold = TRUE, line = "bt", line_color = "#d3d8dc")
}
} else if (!inherits(a, "tinytable") && !inherits(b, "tinytable")) {
Expand All @@ -110,11 +113,11 @@ datasummary_skim <- function(data,
out <- b
}

ofmt <- settings_get("output_format")
ofmt <- output_format
if (isTRUE(ofmt %in% c("latex", "markdown", "html", "typst", "dataframe"))) {
out@output <- ofmt
}
ofile <- settings_get("output_file")
ofile <- output_file
if (!is.null(ofile)) {
tinytable::save_tt(out, output = ofile, overwrite = TRUE)
}
Expand Down Expand Up @@ -154,7 +157,7 @@ datasummary_skim <- function(data,
}
}

if (!is.null(settings_get("output_file"))) {
if (!is.null(output_file)) {
settings_rm()
return(invisible(out))
} else {
Expand Down
9 changes: 6 additions & 3 deletions R/escape.R
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#' Make sure LaTeX and HTML are safe to compile
#'
#' @keywords internal
escape_string <- function(x) {
escape_string <- function(x, output_format = NULL) {
if (is.null(output_format)) {
output_format <- settings_get("output_format")
}
if (settings_equal("escape", TRUE)) {
if (identical(Sys.getenv("pkgdown"), "true") || settings_equal("output_format", c("html", "kableExtra"))) {
if (identical(Sys.getenv("pkgdown"), "true") || output_format %in% c("html", "kableExtra")) {
out <- escape_html(x)
} else if (settings_equal("output_format", c("latex", "latex_tabular"))) {
} else if (output_format %in% c("latex", "latex_tabular")) {
out <- escape_latex(x)
} else {
out <- x
Expand Down
36 changes: 20 additions & 16 deletions R/factory.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,36 @@ factory <- function(tab,
add_rows = NULL,
add_columns = NULL,
escape = TRUE,
output_factory = "tinytable",
output_format = "tinytable",
output_file = NULL,
...) {


# sanity check functions are hosted in R/sanity_checks.R
sanity_title(title, ...)
sanity_notes(notes)
# sanitize_output(output) # do not override (otherwise this breaks quarto for shape="rbind")

# parse output
if (isTRUE(output == "data.frame")) { # internal calls from datasummary_skim()
factory_fun <- factory_dataframe
} else if (settings_equal("output_factory", "gt")) {
} else if (output_factory == "gt") {
factory_fun <- factory_gt
} else if (settings_equal("output_factory", "tinytable")) {
} else if (output_factory == "tinytable") {
factory_fun <- factory_tinytable
} else if (settings_equal("output_factory", "kableExtra")) {
} else if (output_factory == "kableExtra") {
factory_fun <- factory_kableExtra
} else if (settings_equal("output_factory", "flextable")) {
} else if (output_factory == "flextable") {
factory_fun <- factory_flextable
} else if (settings_equal("output_factory", "huxtable")) {
} else if (output_factory == "huxtable") {
factory_fun <- factory_huxtable
} else if (settings_equal("output_factory", "DT")) {
} else if (output_factory == "DT") {
factory_fun <- factory_DT
} else if (settings_equal("output_factory", "dataframe")) {
} else if (output_factory == "dataframe") {
factory_fun <- factory_dataframe
} else if (settings_equal("output_factory", "modelsummary")) {
} else if (output_factory == "modelsummary") {
factory_fun <- factory_markdown
} else if (settings_equal("output_factory", "typst")) {
} else if (output_factory == "typst") {
factory_fun <- factory_typst
}

Expand All @@ -52,8 +54,8 @@ factory <- function(tab,
if (!is.null(flat_header)) {
flat_factories <- c('huxtable', 'dataframe', 'typst')
flat_formats <- c('markdown', 'word', 'powerpoint', 'typst')
if (settings_get("output_factory") %in% flat_factories ||
settings_get("output_format") %in% flat_formats) {
if (output_factory %in% flat_factories ||
output_format %in% flat_formats) {
attr(tab, "header_bottom") <- colnames(tab)

# datasummary_balance with dinm produces more cols than flat_header
Expand All @@ -65,7 +67,7 @@ factory <- function(tab,
}

# de-duplicate columns with whitespace
colnames(tab) <- pad(colnames(tab))
colnames(tab) <- pad(colnames(tab), output_format = output_format)

# add_columns
if (!is.null(add_columns)) {
Expand Down Expand Up @@ -124,7 +126,7 @@ factory <- function(tab,
if (!is.null(add_rows)) {

# data.frame includes metadata columns
if (settings_equal("output_format", "dataframe")) {
if (identical(output_format, "dataframe")) {
# only for modelsummary, not for datasummary

if (all(c("term", "statistic") %in% colnames(tab))) {
Expand Down Expand Up @@ -173,10 +175,10 @@ factory <- function(tab,
align <- strsplit(align, "")[[1]]

# dot align with unicode spaces (latex has its own mechanism)
if (!settings_equal("output_format", c("latex", "tinytable"))) {
if (!output_format %in% c("latex", "tinytable")) {
align_d <- grep("d", align)
for (i in align_d) {
tab[[i]] <- pad(tab[[i]], style = "character")
tab[[i]] <- pad(tab[[i]], style = "character", output_format = output_format)
}
align[align == "d"] <- "c"
}
Expand All @@ -188,6 +190,8 @@ factory <- function(tab,
notes = notes,
title = title,
escape = escape,
output_format = output_format,
output_file = output_file,
...)


Expand Down
7 changes: 3 additions & 4 deletions R/factory_dataframe.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ factory_dataframe <- function(tab,
align = NULL,
hrule = NULL,
notes = NULL,
output_file = NULL,
output_format = NULL,
add_rows = NULL,
title = NULL,
output_file = NULL,
output_format = NULL,
...) {

out <- tab
Expand All @@ -24,7 +24,7 @@ factory_dataframe <- function(tab,
if (!isTRUE(list(...)$internal_call)) {
colnames(out) <- gsub("\\|\\|\\|\\|", " / ", colnames(out))
colnames(out) <- ifelse(colnames(out) == " ", colnames(out), trimws(colnames(out)))
colnames(out) <- pad(trimws(colnames(out)))
colnames(out) <- pad(trimws(colnames(out)), output_format = output_format)
}

# factor -> character (useful for R<4.0.0)
Expand All @@ -49,7 +49,6 @@ factory_dataframe <- function(tab,
out <- theme_ms(out)

# write spreadsheet to file
output_file <- settings_get("output_file")
if (isTRUE(tools::file_ext(output_file) == "csv")) {
utils::write.csv(out, file = output_file, row.names = FALSE)
} else if (isTRUE(tools::file_ext(output_file) == "xlsx")) {
Expand Down
22 changes: 12 additions & 10 deletions R/factory_flextable.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ factory_flextable <- function(tab,
hrule = NULL,
notes = NULL,
title = NULL,
output_format = "flextable",
output_file = NULL,
...) {

insight::check_if_installed("flextable")

span <- get_span_kableExtra(tab)
colnames(tab) <- gsub(".*\\|\\|\\|\\|", "", colnames(tab))
colnames(tab) <- pad(colnames(tab))
colnames(tab) <- pad(colnames(tab), output_format = output_format)

# measurements
table_width <- ncol(tab)
Expand Down Expand Up @@ -51,15 +53,15 @@ factory_flextable <- function(tab,


# output
if (is.null(settings_get("output_file"))) {
if (is.null(output_file)) {
return(out)
} else if (settings_equal("output_format", "word")) {
flextable::save_as_docx(out, path = settings_get("output_file"))
} else if (settings_equal("output_format", "powerpoint")) {
flextable::save_as_pptx(out, path = settings_get("output_file"))
} else if (settings_equal("output_format", "png")) {
flextable::save_as_image(out, path = settings_get("output_file"))
} else if (settings_equal("output_format", "html")) {
flextable::save_as_html(out, path = settings_get("output_file"))
} else if (identical(output_format, "word")) {
flextable::save_as_docx(out, path = output_file)
} else if (identical(output_format, "powerpoint")) {
flextable::save_as_pptx(out, path = output_file)
} else if (identical(output_format, "png")) {
flextable::save_as_image(out, path = output_file)
} else if (identical(output_format, "html")) {
flextable::save_as_html(out, path = output_file)
}
}
Loading
Loading