diff --git a/.gitignore b/.gitignore index ae86318757..bb8552d8b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,27 +1,38 @@ -inst/doc # History files .Rhistory .Rapp.history +# Docs folder from `pkgdown::build_site()` +docs/ +inst/doc + # Session Data files .RData + # Example code in package build process *-Ex.R + # Output files from R CMD build /*.tar.gz + # Output files from R CMD check /*.Rcheck/ + # RStudio files .Rproj.user/ + # produced vignettes vignettes/*.html vignettes/*.pdf + # knitr and R markdown default cache directories /*_cache/ /cache/ + # Temporary files created by R markdown *.utf8.md *.knit.md .Rproj.user + # Other files .DS_Store diff --git a/.travis.yml b/.travis.yml index 4c14b3f7f9..332fb7bb81 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,4 +43,4 @@ jobs: on: all_branches: true github-token: - secure: "VYVhr8KRgfJp5cexTVEciYvlULcCj8z6Qe63UUNw2Ob81vii9e9J450R+gS80qO8TYxwhrzkby21CESHwGbXIn6J9skW/V0CDlIHb/GGmwSKLUnbRT5X0On89Zogqz+yiY6HUa4oRZUSdFqo4pLjq56UHy/PK/GvAkDCA4tOKLc7qm9nwXov3NZJssgCo24beYq2FxXb2ifEfJ06/oB5E2/aR1E6HktR0KvbLspGP7DboRl/rbTg0wxpNAyUu49ZbRlC4I7Zl2tzehlq6MIO3u+0yVe7hyCwcrWBZbBLsekJ1tRlEs1Wh+O2q2NMSNFRmA8e3awQo7GO+maQRl2PFsO9Mn7P2oVRwaJzHkz+QKRtyJB8oNjwEJQDo2M0jW3ggEhQyO039tDic1b3iYi8QORBSwCkn6TbFlFedNdlnBhXskk7fSH4GEkr7Fq6//xKFRvEKZuLCKIbrCOnQxuDI6Ak7OWe1A1cXlOqDcvuLBg5ZFMvXMh3RrE4z4AoGyPr2xY3lOM1hoHDtjLBAAAJ7IpH251qAahsCxBLhWufHQ6xmz020aV8mg89KVsU58SbVBKwjyFRoR+1IaTb/dsxtWItW5AMh5kwwH36PQp2L7eixBBFUAyJaEpoNEGTJg24B5QJPMDfu1MXEkSBisrwtuKYzRuJ/XJd77Z47BkukEc=" + secure: "GrujWLlpdgy59mI5ZiYnlT8p1LDpqoms/ROeBuFOhJ6tZa6lNYzG4tR2iGkJS5a9hykMbkDootmx95ktC/ovjvFrWXLb8Ql+XiWri1cb17G3SzcEz7m35RA6fKNsu9BVM1qhydBnSS6UtFGWkK/+4dqkT3/3b7XnO2WmF8MtFno9iPnBRybgIYjt5qrBNUZQPcvkjL6FV1x2X2O5lwrH4ND7ueM6wgs5BtxCQxhaBcu9gmDbjlnPsfCbqQvxVNuifguF9AzDPE97nylDyr9jeycehWkvHioFKjYhK/yWfANuXGOgYb0I+vCyxDfxIrOfc+IhUEGaSxqZ3H3fy3Mdc8Bd2+IhC6KbdpSJiB57N1OPIHj6I8a9YlELZN2EczDXUxfvppTlDYBAWUpfI2uPoBMskBTgPXP838u+jNrAcMERkNAIgb4VOPVnf+MbGei2gfSWXmFvH+z0EjwpPxhv0nP1+5TT2RsErwpEyrA8qO14uICx+/gKPZulMKeZApjWYtOyJRjeRYPFUwrLx8S52CeR1el5QyiuPke9oTxmg9gMuoVWGReoDvtOIaz6LbgUPy9/o+gHNPb70DLYii9h2thzJtMTr30jnpGsosIaBghpregaOvxEIyo5xJGRBn9z0R1n6VnRWjyIC/VTh0ljn1pvC26LVrQj7DKa8SMP6Jw=" diff --git a/R/datasets.R b/R/datasets.R index df3bb9c993..3b73aa03d2 100644 --- a/R/datasets.R +++ b/R/datasets.R @@ -179,7 +179,7 @@ #' \item \code{southw_ckn}: The Southwest Chicken Pizza (Chicken, Tomatoes, Red #' Peppers, Red Onions, Jalapeno Peppers, Corn, Cilantro, Chipotle Sauce) #' \item \code{cali_ckn}: The California Chicken Pizza (Chicken, Artichoke, -#' Spinach, Garlic, JalapeƱo Peppers, Fontina Cheese, Gouda Cheese) +#' Spinach, Garlic, Jalapeno Peppers, Fontina Cheese, Gouda Cheese) #' \item \code{ckn_pesto}: The Chicken Pesto Pizza (Chicken, Tomatoes, Red #' Peppers, Spinach, Garlic, Pesto Sauce) #' \item \code{ckn_alfredo}: The Chicken Alfredo Pizza (Chicken, Red Onions, diff --git a/R/format_data.R b/R/format_data.R index 4fac619875..1d6b566b36 100644 --- a/R/format_data.R +++ b/R/format_data.R @@ -142,37 +142,84 @@ fmt_number <- function(data, locale = NULL) { # Use locale-based marks if a locale ID is provided - if (!is.null(locale) && locale %in% locales$base_locale_id) { - sep_mark <- get_locale_sep_mark(locale = locale) - dec_mark <- get_locale_dec_mark(locale = locale) - } else if (!is.null(locale) && !(locale %in% locales$base_locale_id)) { - stop("The supplied `locale` is not available in the list of supported locales.", - call. = FALSE) - } + sep_mark <- get_locale_sep_mark(locale, sep_mark, use_seps) + dec_mark <- get_locale_dec_mark(locale, dec_mark) - # Provide an empty string for `sep_mark` if we choose - # to not use digit group separators - if (!use_seps) { - sep_mark <- "" - } + # Normalize the `suffixing` input to either return a character vector + # of suffix labels, or NULL (the case where `suffixing` is FALSE) + suffix_labels <- normalize_suffixing_inputs(suffixing, scale_by) - # Normalize the `suffixing` input to either return a - # character vector of suffix labels, or NULL (the - # case where `suffixing` is FALSE) - suffix_labels <- normalize_suffixing_inputs(suffixing) + # Create a function factory for the `fmt_number()` function + fmt_number_factory <- function(context = "html") { - # If choosing to perform large-number suffixing - # of numeric values, force `scale_by` to be 1.0 - if (!is.null(suffix_labels)) { + function(x) { - if (!missing(scale_by) && !identical(scale_by, 1.0)) { - warning("The value for `scale_by` can't be changed if `suffixing` is ", - "anything other than `FALSE`. The value provided to `scale_by` ", - "will be ignored.", - call. = FALSE) - } + # Define the marks by context + minus_mark <- context_minus_mark(context) + parens_marks <- context_parens_marks_number(context) + + # Determine which of `x` are not NA + non_na_x <- !is.na(x) + + # Create a possibly shorter vector of non-NA `x` values + x_vals <- x[non_na_x] + + # Create a tibble with scaled values for `x[non_na_x]` + # and the suffix labels to use for character formatting + suffix_df <- + num_suffix( + round(x_vals, decimals), + suffixes = suffix_labels, + scale_by = scale_by + ) + + # Scale the `x_vals` by the `scale_by` value + x_vals <- scale_x_values(x_vals, scale_by = suffix_df$scale_by) + + # Format all non-NA x values + x_str_vals <- + format_num_to_str( + x_vals, decimals, sep_mark, dec_mark, drop_trailing_zeros + ) + + # Paste vector of suffixes to the right of the `x_str_vals` + x_str_vals <- paste_right(x_str_vals, suffix_df$suffix) + + # Perform negative value formatting + if (any(x_vals < 0)) { + + # Handle replacement of the minus mark + x_str_vals <- + x_str_vals %>% + tidy_gsub("-", minus_mark, fixed = TRUE) + + # Handle case where negative values are to be placed within parentheses + if (negative_val == "parens") { + + # Selectively remove minus sign and paste between parentheses + x_str_vals[x_vals < 0] <- + paste_between( + x = gsub(paste0("^", minus_mark), "", x_str_vals[x_vals < 0]), + x_2 = parens_marks + ) + } + } + + # If in a LaTeX context, remove any double negative + # signs in the exponent + if (context == "latex") { + x_str_vals <- to_latex_math_mode(x_str_vals) + } + + # Handle formatting of pattern + x_str_vals <- apply_pattern_fmt_x(pattern, x_str_vals) - scale_by <- 1.0 + # Create `x_str` with the same length as `x`; place the + # `x_str_vals` into `str` (at the non-NA indices) + x_str <- rep(NA_character_, length(x)) + x_str[non_na_x] <- x_str_vals + x_str + } } # Capture expression in `rows` and `columns` @@ -181,79 +228,23 @@ fmt_number <- function(data, # Pass `data`, `columns`, `rows`, and the formatting # functions as a function list to `fmt()` - fmt(data = data, - columns = !!columns, - rows = !!rows, - fns = list( - default = function(x) { - - # Determine which of `x` are not NA - non_na_x <- !is.na(x) - - # Create a tibble with scaled values for - # `x[non_na_x]` and the suffix labels to - # use for character formatting - suffix_df <- - num_suffix( - x = round(x[non_na_x], decimals), - suffixes = suffix_labels - ) - - # If choosing to perform large-number suffixing - # of numeric values, replace `scale_by` with - # a vector of scaling values (of equal length - # with `x[non_na_x]`) - if (!is.null(suffix_labels)) { - scale_by <- suffix_df$scale_by[non_na_x] - } - - # Create `x_str` with same length as `x` - x_str <- rep(NA_character_, length(x)) - - # Format all non-NA x values - x_str[non_na_x] <- - formatC( - x = x[non_na_x] * scale_by, - digits = decimals, - mode = "double", - big.mark = sep_mark, - decimal.mark = dec_mark, - format = "f", - drop0trailing = drop_trailing_zeros) - - # Apply large-number suffixes to scaled and - # formatted values if that option is taken - if (!is.null(suffix_labels)) { - - # Apply vector of suffixes - x_str[non_na_x] <- - paste0(x_str[non_na_x], suffix_df$suffix[non_na_x]) - } - - # Handle negative values - if (negative_val == "parens") { - - # Determine which of `x` are not NA and also negative - negative_x <- x < 0 & !is.na(x) - - # Apply parentheses to the formatted value and remove - # the minus sign - x_str[negative_x] <- paste0("(", gsub("^-", "", x_str[negative_x]), ")") - } - - # Handle formatting of pattern - pre_post_txt <- get_pre_post_txt(pattern) - x_str[non_na_x] <- paste0(pre_post_txt[1], x_str[non_na_x], pre_post_txt[2]) - x_str - } - )) + fmt( + data = data, + columns = !!columns, + rows = !!rows, + fns = list( + html = fmt_number_factory(context = "html"), + latex = fmt_number_factory(context = "latex"), + default = fmt_number_factory(context = "default") + ) + ) } #' Format values to scientific notation #' -#' With numeric values in a \pkg{gt} table, we can perform formatting so that -#' the targeted values are presented in scientific notation. We can exert finer -#' finer control on the formatting with the following options: +#' With numeric values in a \pkg{gt} table, we can perform formatting so that the +#' targeted values are rendered in scientific notation. Furthermore, there is +#' fine control with the following options: #' \itemize{ #' \item decimals: choice of the number of decimal places, option to drop #' trailing zeros, and a choice of the decimal symbol @@ -312,89 +303,82 @@ fmt_scientific <- function(data, locale = NULL) { # Use locale-based marks if a locale ID is provided - if (!is.null(locale) && locale %in% locales$base_locale_id) { - sep_mark <- get_locale_sep_mark(locale = locale) - dec_mark <- get_locale_dec_mark(locale = locale) - } else if (!is.null(locale) && !(locale %in% locales$base_locale_id)) { - stop("The supplied `locale` is not available in the list of supported locales.", - call. = FALSE) - } + sep_mark <- get_locale_sep_mark(locale, sep_mark, use_seps = TRUE) + dec_mark <- get_locale_dec_mark(locale, dec_mark) - format_fcn_sci_notn_factory <- function(exp_start_str, exp_end_str) { + # Create a function factory for the `fmt_scientific()` function + fmt_scientific_factory <- function(context = "html") { function(x) { + # Define the marks by context + minus_mark <- context_minus_mark(context) + exp_marks <- context_exp_marks(context) + # Determine which of `x` are not NA non_na_x <- !is.na(x) - # Determine which of `x` don't require scientific notation - small_pos <- - ((x >= 1 & x < 10) | - (x <= -1 & x > -10) | - x == 0) & !is.na(x) + # Create a possibly shorter vector of non-NA `x` values + x_vals <- x[non_na_x] - # Create `x_str` with same length as `x` - x_str <- rep(NA_character_, length(x)) + # Scale the `x_vals` by the `scale_by` value + x_vals <- scale_x_values(x_vals, scale_by) + + # Determine which of `x` don't require the (x 10^n) + # since their order would be zero + small_pos <- has_order_zero(x_vals) - # Format the number component as a character vector - x_str[non_na_x] <- - formatC( - x = x[non_na_x] * scale_by, - digits = decimals, - mode = "double", - big.mark = sep_mark, - decimal.mark = dec_mark, - format = "e", - drop0trailing = drop_trailing_zeros) + # Format all non-NA x values + x_str_vals <- + format_num_to_str_e( + x_vals, decimals, sep_mark, dec_mark, + drop_trailing_zeros + ) # For any numbers that shouldn't have an exponent, remove # that portion from the character version if (any(small_pos)) { - x_str[small_pos] <- - split_scientific_notn(x_str[small_pos])$num + + x_str_vals[small_pos] <- + split_scientific_notn(x_str_vals[small_pos])$num } # For any non-NA numbers that do have an exponent, format # those according to the output context if (any(!small_pos)) { - sci_parts <- split_scientific_notn(x_str[non_na_x & !small_pos]) + sci_parts <- split_scientific_notn(x_str_vals[!small_pos]) - x_str[non_na_x & !small_pos] <- + x_str_vals[!small_pos] <- paste0( - sci_parts$num, exp_start_str, - sci_parts$exp, exp_end_str + sci_parts$num, exp_marks[1], + sci_parts$exp, exp_marks[2] ) } + # Handle replacement of the minus mark in number + # and exponent parts + x_str_vals <- + x_str_vals %>% + tidy_gsub("-", minus_mark, fixed = TRUE) + + # If in a LaTeX context, put formatted numbers + # in math mode + if (context == "latex") { + x_str_vals <- to_latex_math_mode(x_str_vals) + } + # Handle formatting of pattern - pre_post_txt <- get_pre_post_txt(pattern) - x_str[non_na_x] <- paste0(pre_post_txt[1], x_str[non_na_x], pre_post_txt[2]) + x_str_vals <- apply_pattern_fmt_x(pattern, x_str_vals) + + # Create `x_str` with the same length as `x`; place the + # `x_str_vals` into `str` (at the non-NA indices) + x_str <- rep(NA_character_, length(x)) + x_str[non_na_x] <- x_str_vals x_str } } - # Create the default formatting function for scientific notation - format_fcn_sci_notn_default <- - format_fcn_sci_notn_factory( - exp_start_str = " x 10(", - exp_end_str = ")" - ) - - # Create the HTML formatting function for scientific notation - format_fcn_sci_notn_html <- - format_fcn_sci_notn_factory( - exp_start_str = " × 10", - exp_end_str = "" - ) - - # Create the LaTeX formatting function for scientific notation - format_fcn_sci_notn_latex <- - format_fcn_sci_notn_factory( - exp_start_str = "$ \\times 10^{", - exp_end_str = "}$" - ) - # Capture expression in `rows` and `columns` rows <- rlang::enquo(rows) columns <- rlang::enquo(columns) @@ -406,9 +390,10 @@ fmt_scientific <- function(data, columns = !!columns, rows = !!rows, fns = list( - html = format_fcn_sci_notn_html, - default = format_fcn_sci_notn_default, - latex = format_fcn_sci_notn_latex) + html = fmt_scientific_factory(context = "html"), + latex = fmt_scientific_factory(context = "latex"), + default = fmt_scientific_factory(context = "default") + ) ) } @@ -484,135 +469,103 @@ fmt_percent <- function(data, locale = NULL) { # Use locale-based marks if a locale ID is provided - if (!is.null(locale) && locale %in% locales$base_locale_id) { - sep_mark <- get_locale_sep_mark(locale = locale) - dec_mark <- get_locale_dec_mark(locale = locale) - } else if (!is.null(locale) && !(locale %in% locales$base_locale_id)) { - stop("The supplied `locale` is not available in the list of supported locales.", - call. = FALSE) - } - - # Provide an empty string for `sep_mark` if we choose - # to not use digit group separators - if (!use_seps) { - sep_mark <- "" - } - - # Capture expression in `rows` and `columns` - rows <- rlang::enquo(rows) - columns <- rlang::enquo(columns) - - # Pass `data`, `columns`, `rows`, and the formatting - # functions as a function list to `fmt()` - fmt(data = data, - columns = !!columns, - rows = !!rows, - fns = list( - latex = function(x) { - - # Determine which of `x` are not NA - non_na_x <- !is.na(x) - - # Create `x_str` with same length as `x` - x_str <- rep(NA_character_, length(x)) - - # Format all non-NA x values - x_str[non_na_x] <- - formatC( - x = x[non_na_x] * 100.0, - digits = decimals, - mode = "double", - big.mark = sep_mark, - decimal.mark = dec_mark, - format = "f", - drop0trailing = drop_trailing_zeros) - - if (placement == "right") { - - x_str[non_na_x] <- - paste0( - x_str[non_na_x], - ifelse(incl_space, " \\%", "\\%") - ) - - } else { - - x_str[non_na_x] <- - paste0( - ifelse(incl_space, "\\% ", "\\%"), - x_str[non_na_x] - ) - } + sep_mark <- get_locale_sep_mark(locale, sep_mark, use_seps) + dec_mark <- get_locale_dec_mark(locale, dec_mark) - # Handle negative values - if (negative_val == "parens") { + # Create a function factory for the `fmt_percent()` function + fmt_percent_factory <- function(context = "html") { - # Determine which of `x` are not NA and also negative - negative_x <- x < 0 & !is.na(x) - - # Apply parentheses to the formatted value and remove - # the minus sign - x_str[negative_x] <- paste0("(", gsub("^-", "", x_str[negative_x]), ")") - } + function(x) { - # Handle formatting of pattern - pre_post_txt <- get_pre_post_txt(pattern) - x_str[non_na_x] <- paste0(pre_post_txt[1], x_str[non_na_x], pre_post_txt[2]) - x_str - }, - default = function(x) { + # Define the marks by context + minus_mark <- context_minus_mark(context) + percent_mark <- context_percent_mark(context) + parens_marks <- context_parens_marks(context) - # Determine which of `x` are not NA - non_na_x <- !is.na(x) + # Determine which of `x` are not NA + non_na_x <- !is.na(x) - # Create `x_str` with same length as `x` - x_str <- rep(NA_character_, length(x)) + # Create a possibly shorter vector of non-NA `x` values + x_vals <- x[non_na_x] + + # Scale the `x_vals` by the `scale_by` value + x_vals <- scale_x_values(x_vals, scale_by = 100) + + # Format all non-NA x values + x_str_vals <- + format_num_to_str( + x_vals, decimals, sep_mark, dec_mark, drop_trailing_zeros + ) + + # Handle placement of the percent symbol + x_str_vals <- + x_str_vals %>% + paste_on_side( + x_side = ifelse(incl_space, " ", ""), + direction = placement + ) %>% + paste_on_side( + x_side = percent_mark, + direction = placement + ) %>% + swap_adjacent_text_groups( + pattern_1 = percent_mark, + pattern_2 = "-" + ) + + # Perform negative value formatting + if (any(x_vals < 0)) { + + # Handle replacement of the minus mark + x_str_vals <- + x_str_vals %>% + tidy_gsub("-", minus_mark, fixed = TRUE) + + # Handle case where negative values are to be placed within parentheses + if (negative_val == "parens") { + + # Selectively remove minus sign and paste between parentheses + x_str_vals[x_vals < 0] <- + paste_between( + x = gsub(paste0("^", minus_mark), "", x_str_vals[x_vals < 0]), + x_2 = parens_marks + ) + } + } - # Format all non-NA x values - x_str[non_na_x] <- - formatC( - x = x[non_na_x] * 100.0, - digits = decimals, - mode = "double", - big.mark = sep_mark, - decimal.mark = dec_mark, - format = "f", - drop0trailing = drop_trailing_zeros) - - if (placement == "right") { - - x_str[non_na_x] <- - paste0( - x_str[non_na_x], - ifelse(incl_space, " %", "%") - ) - - } else { - - x_str[non_na_x] <- - paste0( - ifelse(incl_space, "% ", "%"), - x_str[non_na_x] - ) - } + # If in a LaTeX context, remove any double negative + # signs in the exponent + if (context == "latex") { + x_str_vals <- to_latex_math_mode(x_str_vals) + } - # Handle negative values - if (negative_val == "parens") { + # Handle formatting of pattern + x_str_vals <- apply_pattern_fmt_x(pattern, x_str_vals) - # Determine which of `x` are not NA and also negative - negative_x <- x < 0 & !is.na(x) + # Create `x_str` with the same length as `x`; place the + # `x_str_vals` into `str` (at the non-NA indices) + x_str <- rep(NA_character_, length(x)) + x_str[non_na_x] <- x_str_vals + x_str + } + } - # Apply parentheses to the formatted value and remove - # the minus sign - x_str[negative_x] <- paste0("(", gsub("^-", "", x_str[negative_x]), ")") - } + # Capture expression in `rows` and `columns` + rows <- rlang::enquo(rows) + columns <- rlang::enquo(columns) - # Handle formatting of pattern - pre_post_txt <- get_pre_post_txt(pattern) - x_str[non_na_x] <- paste0(pre_post_txt[1], x_str[non_na_x], pre_post_txt[2]) - x_str - } - )) + # Pass `data`, `columns`, `rows`, and the formatting + # functions as a function list to `fmt()` + fmt( + data = data, + columns = !!columns, + rows = !!rows, + fns = list( + html = fmt_percent_factory(context = "html"), + latex = fmt_percent_factory(context = "latex"), + default = fmt_percent_factory(context = "default") + ) + ) } #' Format values as currencies @@ -726,63 +679,100 @@ fmt_currency <- function(data, locale = NULL) { # Use locale-based marks if a locale ID is provided - if (!is.null(locale) && locale %in% locales$base_locale_id) { - sep_mark <- get_locale_sep_mark(locale = locale) - dec_mark <- get_locale_dec_mark(locale = locale) - } else if (!is.null(locale) && !(locale %in% locales$base_locale_id)) { - stop("The supplied `locale` is not available in the list of supported locales.", - call. = FALSE) - } + sep_mark <- get_locale_sep_mark(locale, sep_mark, use_seps) + dec_mark <- get_locale_dec_mark(locale, dec_mark) # Stop function if `currency` does not have a valid value - if (!is_currency_valid(currency)) { - stop("The supplied `currency` is not available in the list of supported currencies.", - call. = FALSE) - } + validate_currency(currency) - # Get the currency string for the HTML context - currency_str_html <- get_currency_str(currency) + # Get the number of decimal places + decimals <- get_currency_decimals(currency, decimals, use_subunits) - # Get the currency string for the non-HTML context - currency_str <- get_currency_str(currency, fallback_to_code = TRUE) + # Normalize the `suffixing` input to either return a character vector + # of suffix labels, or NULL (the case where `suffixing` is FALSE) + suffix_labels <- normalize_suffixing_inputs(suffixing, scale_by) - # Get the number of decimal places - if (is.null(decimals) & use_subunits) { + # Create a function factory for the `fmt_currency()` function + fmt_currency_factory <- function(context = "html") { - # Get decimal places using `get_currency_exponent()` fcn - if (currency %in% currency_symbols$curr_symbol) { - decimals <- 2 - } else { - decimals <- get_currency_exponent(currency = currency) - } + function(x) { - } else if (is.null(decimals) & use_subunits == FALSE) { - decimals <- 0 - } + # Define the marks by context + negative_currency_mark <- context_negative_currency_mark(context) + currency_str <- context_currency_str(context, currency) + currency_str_regex <- context_currency_str_regex(context) + parens_marks <- context_parens_marks(context) - # Provide an empty string for `sep_mark` if we choose - # to not use digit group separators - if (!use_seps) { - sep_mark <- "" - } + # Determine which of `x` are not NA + non_na_x <- !is.na(x) + + # Create a possibly shorter vector of non-NA `x` values + x_vals <- x[non_na_x] + + # Create a tibble with scaled values for `x[non_na_x]` + # and the suffix labels to use for character formatting + suffix_df <- + num_suffix( + round(x_vals, decimals), + suffixes = suffix_labels, + scale_by = scale_by + ) + + # Scale the `x_vals` by the `scale_by` value + x_vals <- scale_x_values(x_vals, scale_by = suffix_df$scale_by) + + # Format all non-NA x values + x_str_vals <- format_num_to_str_c(x_vals, decimals, sep_mark, dec_mark) + + # Paste vector of suffixes to the right of the `x_str_vals` + x_str_vals <- paste_right(x_str_vals, suffix_df$suffix) + + # Handle placement of the currency symbol + x_str_vals <- + x_str_vals %>% + paste_currency_str(currency_str, incl_space, placement) + + # Perform negative value formatting + if (any(x_vals < 0)) { + + # Handle replacement of the minus mark + x_str_vals <- + x_str_vals %>% + tidy_gsub("-", negative_currency_mark, fixed = TRUE) + + # Handle case where negative values are to be placed within parentheses + if (negative_val == "parens") { + + # Selectively remove minus sign and paste between parentheses + x_str_vals[x_vals < 0] <- + paste_between( + x = x_str_vals[x_vals < 0] %>% + tidy_gsub( + negative_currency_mark, "", + fixed = TRUE + ), + x_2 = parens_marks + ) + } + } - # Normalize the `suffixing` input to either return a - # character vector of suffix labels, or NULL (the - # case where `suffixing` is FALSE) - suffix_labels <- normalize_suffixing_inputs(suffixing) + # If in a LaTeX context, wrap values in math mode + if (context == "latex") { - # If choosing to perform large-number suffixing - # of numeric values, force `scale_by` to be 1.0 - if (!is.null(suffix_labels)) { + x_str_vals <- + x_str_vals %>% + to_latex_math_mode() + } - if (!missing(scale_by) && !identical(scale_by, 1.0)) { - warning("The value for `scale_by` can't be changed if `suffixing` is ", - "anything other than `FALSE`. The value provided to `scale_by` ", - "will be ignored.", - call. = FALSE) - } + # Handle formatting of pattern + x_str_vals <- apply_pattern_fmt_x(pattern, x_str_vals) - scale_by <- 1.0 + # Create `x_str` with the same length as `x`; place the + # `x_str_vals` into `str` (at the non-NA indices) + x_str <- rep(NA_character_, length(x)) + x_str[non_na_x] <- x_str_vals + x_str + } } # Capture expression in `rows` and `columns` @@ -791,248 +781,16 @@ fmt_currency <- function(data, # Pass `data`, `columns`, `rows`, and the formatting # functions as a function list to `fmt()` - fmt(data = data, - columns = !!columns, - rows = !!rows, - fns = list( - default = function(x) { - - # Determine which of `x` are not NA - non_na_x <- !is.na(x) - - # Determine which of `x` are not NA and also negative - negative_x <- x < 0 & !is.na(x) - - # Create `x_str` with same length as `x` - x_str <- rep(NA_character_, length(x)) - - # Create a tibble with scaled values for - # `x[non_na_x]` and the suffix labels to - # use for character formatting - suffix_df <- - num_suffix( - x = round(x[non_na_x], decimals), - suffixes = suffix_labels - ) - - # If choosing to perform large-number suffixing - # of numeric values, replace `scale_by` with - # a vector of scaling values (of equal length - # with `x[non_na_x]`) - if (!is.null(suffix_labels)) { - scale_by <- suffix_df$scale_by[non_na_x] - } - - # Format all non-NA x values - x_str[non_na_x] <- - formatC( - x = x[non_na_x] * scale_by, - digits = decimals, - mode = "double", - big.mark = sep_mark, - decimal.mark = dec_mark, - format = "f", - drop0trailing = FALSE) - - # Apply large-number suffixes to scaled and - # formatted values if that option is taken - if (!is.null(suffix_labels)) { - - # Apply vector of suffixes - x_str[non_na_x] <- - paste0(x_str[non_na_x], suffix_df$suffix[non_na_x]) - } - - # Handle placement of the currency symbol - if (placement == "left") { - - x_str[non_na_x] <- - paste0( - currency_str, - ifelse(incl_space, " ", ""), x_str[non_na_x] - ) - - } else { - - x_str[non_na_x] <- - paste0( - x_str[non_na_x], - ifelse(incl_space, " ", ""), currency_str - ) - } - - # Handle negative values - if (negative_val == "parens") { - - # Apply parentheses to the formatted value and remove - # the minus sign - x_str[negative_x] <- paste0("(", gsub("-", "", x_str[negative_x]), ")") - } - - # Handle formatting of pattern - pre_post_txt <- get_pre_post_txt(pattern) - x_str[non_na_x] <- paste0(pre_post_txt[1], x_str[non_na_x], pre_post_txt[2]) - x_str - }, - html = function(x) { - - # Determine which of `x` are not NA - non_na_x <- !is.na(x) - - # Determine which of `x` are not NA and also negative - negative_x <- x < 0 & !is.na(x) - - # Create `x_str` with same length as `x` - x_str <- rep(NA_character_, length(x)) - - # Create a tibble with scaled values for - # `x[non_na_x]` and the suffix labels to - # use for character formatting - suffix_df <- - num_suffix( - x = round(x[non_na_x], decimals), - suffixes = suffix_labels - ) - - # If choosing to perform large-number suffixing - # of numeric values, replace `scale_by` with - # a vector of scaling values (of equal length - # with `x[non_na_x]`) - if (!is.null(suffix_labels)) { - scale_by <- suffix_df$scale_by[non_na_x] - } - - # Format all non-NA x values - x_str[non_na_x] <- - formatC( - x = x[non_na_x] * scale_by, - digits = decimals, - mode = "double", - big.mark = sep_mark, - decimal.mark = dec_mark, - format = "f", - drop0trailing = FALSE) - - # Apply large-number suffixes to scaled and - # formatted values if that option is taken - if (!is.null(suffix_labels)) { - - # Apply vector of suffixes - x_str[non_na_x] <- - paste0(x_str[non_na_x], suffix_df$suffix[non_na_x]) - } - - # Handle placement of the currency symbol - if (placement == "left") { - - x_str[non_na_x] <- - paste0( - currency_str_html, - ifelse(incl_space, " ", ""), x_str[non_na_x] - ) - - } else { - - x_str[non_na_x] <- - paste0( - x_str[non_na_x], - ifelse(incl_space, " ", ""), currency_str_html - ) - } - - # Handle negative values - if (negative_val == "parens") { - - # Apply parentheses to the formatted value and remove - # the minus sign - x_str[negative_x] <- paste0("(", gsub("-", "", x_str[negative_x]), ")") - } - - # Handle formatting of pattern - pre_post_txt <- get_pre_post_txt(pattern) - x_str[non_na_x] <- paste0(pre_post_txt[1], x_str[non_na_x], pre_post_txt[2]) - x_str - }, - latex = function(x) { - - # Determine which of `x` are not NA - non_na_x <- !is.na(x) - - # Determine which of `x` are not NA and also negative - negative_x <- x < 0 & !is.na(x) - - # Create `x_str` with same length as `x` - x_str <- rep(NA_character_, length(x)) - - # Create a tibble with scaled values for - # `x[non_na_x]` and the suffix labels to - # use for character formatting - suffix_df <- - num_suffix( - x = round(x[non_na_x], decimals), - suffixes = suffix_labels - ) - - # If choosing to perform large-number suffixing - # of numeric values, replace `scale_by` with - # a vector of scaling values (of equal length - # with `x[non_na_x]`) - if (!is.null(suffix_labels)) { - scale_by <- suffix_df$scale_by[non_na_x] - } - - # Format all non-NA x values - x_str[non_na_x] <- - formatC( - x = x[non_na_x] * scale_by, - digits = decimals, - mode = "double", - big.mark = sep_mark, - decimal.mark = dec_mark, - format = "f", - drop0trailing = FALSE) - - # Apply large-number suffixes to scaled and - # formatted values if that option is taken - if (!is.null(suffix_labels)) { - - # Apply vector of suffixes - x_str[non_na_x] <- - paste0(x_str[non_na_x], suffix_df$suffix[non_na_x]) - } - - # Handle placement of the currency symbol - if (placement == "left") { - - x_str[non_na_x] <- - paste0( - markdown_to_latex(currency_str), - ifelse(incl_space, " ", ""), x_str[non_na_x] - ) - - } else { - - x_str[non_na_x] <- - paste0( - x_str[non_na_x], ifelse(incl_space, " ", ""), - markdown_to_latex(currency_str) - ) - } - - # Handle negative values - if (negative_val == "parens") { - - # Apply parentheses to the formatted value and remove - # the minus sign - x_str[negative_x] <- paste0("(", gsub("-", "", x_str[negative_x]), ")") - } - - # Handle formatting of pattern - pre_post_txt <- get_pre_post_txt(pattern) - x_str[non_na_x] <- paste0(pre_post_txt[1], x_str[non_na_x], pre_post_txt[2]) - x_str - } - )) + fmt( + data = data, + columns = !!columns, + rows = !!rows, + fns = list( + html = fmt_currency_factory(context = "html"), + latex = fmt_currency_factory(context = "latex"), + default = fmt_currency_factory(context = "default") + ) + ) } #' Format values as dates @@ -1549,9 +1307,13 @@ fmt_passthrough <- function(data, # Create `x_str` with same length as `x` x_str <- rep(NA_character_, length(x)) + # TODO: Deal with NA values in x # Handle formatting of pattern - pre_post_txt <- get_pre_post_txt(pattern) - x_str <- paste0(pre_post_txt[1], x, pre_post_txt[2]) + x_str <- + apply_pattern_fmt_x( + pattern, + values = x + ) if (escape) { x_str <- x_str %>% process_text(context = "html") @@ -1564,9 +1326,13 @@ fmt_passthrough <- function(data, # Create `x_str` with same length as `x` x_str <- rep(NA_character_, length(x)) + # TODO: Deal with NA values in x # Handle formatting of pattern - pre_post_txt <- get_pre_post_txt(pattern) - x_str <- paste0(pre_post_txt[1], x, pre_post_txt[2]) + x_str <- + apply_pattern_fmt_x( + pattern, + values = x + ) if (escape) { x_str <- x_str %>% process_text(context = "latex") @@ -1579,9 +1345,13 @@ fmt_passthrough <- function(data, # Create `x_str` with same length as `x` x_str <- rep(NA_character_, length(x)) + # TODO: Deal with NA values in x # Handle formatting of pattern - pre_post_txt <- get_pre_post_txt(pattern) - x_str <- paste0(pre_post_txt[1], x, pre_post_txt[2]) + x_str <- + apply_pattern_fmt_x( + pattern, + values = x + ) x_str } diff --git a/R/gt_options_default.R b/R/gt_options_default.R index 511267ecfc..71e8afef66 100644 --- a/R/gt_options_default.R +++ b/R/gt_options_default.R @@ -17,24 +17,24 @@ gt_options_default <- function() { "column_labels_background_color", TRUE, "columns", NA_character_, "column_labels_font_size", TRUE, "columns", "16px", "column_labels_font_weight", TRUE, "columns", "initial", - "stub_group_background_color", TRUE, "stub_group", NA_character_, - "stub_group_font_size", TRUE, "stub_group", "16px", - "stub_group_font_weight", TRUE, "stub_group", "initial", - "stub_group_border_top_style", TRUE, "stub_group", "solid", - "stub_group_border_top_width", TRUE, "stub_group", "2px", - "stub_group_border_top_color", TRUE, "stub_group", "#A8A8A8", - "stub_group_border_bottom_style", TRUE, "stub_group", "solid", - "stub_group_border_bottom_width", TRUE, "stub_group", "2px", - "stub_group_border_bottom_color", TRUE, "stub_group", "#A8A8A8", - "field_border_top_style", TRUE, "field", "solid", - "field_border_top_width", TRUE, "field", "2px", - "field_border_top_color", TRUE, "field", "#A8A8A8", - "field_border_bottom_style", TRUE, "field", "solid", - "field_border_bottom_width", TRUE, "field", "2px", - "field_border_bottom_color", TRUE, "field", "#A8A8A8", + "row_group_background_color", TRUE, "row_group", NA_character_, + "row_group_font_size", TRUE, "row_group", "16px", + "row_group_font_weight", TRUE, "row_group", "initial", + "row_group_border_top_style", TRUE, "row_group", "solid", + "row_group_border_top_width", TRUE, "row_group", "2px", + "row_group_border_top_color", TRUE, "row_group", "#A8A8A8", + "row_group_border_bottom_style", TRUE, "row_group", "solid", + "row_group_border_bottom_width", TRUE, "row_group", "2px", + "row_group_border_bottom_color", TRUE, "row_group", "#A8A8A8", + "table_body_border_top_style", TRUE, "table_body", "solid", + "table_body_border_top_width", TRUE, "table_body", "2px", + "table_body_border_top_color", TRUE, "table_body", "#A8A8A8", + "table_body_border_bottom_style", TRUE, "table_body", "solid", + "table_body_border_bottom_width", TRUE, "table_body", "2px", + "table_body_border_bottom_color", TRUE, "table_body", "#A8A8A8", "row_padding", TRUE, "row", "8px", "row_striping_include_stub", TRUE, "row", "TRUE", - "row_striping_include_field", TRUE, "row", "TRUE", + "row_striping_include_table_body", TRUE, "row", "TRUE", "summary_row_background_color", TRUE, "summary_row", NA_character_, "summary_row_padding", TRUE, "summary_row", "8px", "summary_row_text_transform", TRUE, "summary_row", "inherit", diff --git a/R/helpers.R b/R/helpers.R index d39bd6c3a8..b6fbfbf271 100644 --- a/R/helpers.R +++ b/R/helpers.R @@ -26,10 +26,10 @@ #' \item \code{cells_stub()}: targets row labels in the table stub using the #' \code{rows} argument. #' -#' \item \code{cells_data()}: targets data cells in the table field using +#' \item \code{cells_data()}: targets data cells in the table body using #' intersections of \code{columns} and \code{rows}. #' -#' \item \code{cells_summary()}: targets summary cells in the table field using +#' \item \code{cells_summary()}: targets summary cells in the table body using #' the \code{groups} argument and intersections of \code{columns} and #' \code{rows}. #' } diff --git a/R/info_tables.R b/R/info_tables.R index 500d23bb10..853bd2d487 100644 --- a/R/info_tables.R +++ b/R/info_tables.R @@ -450,9 +450,11 @@ info_paletteer <- function(color_pkgs = NULL) { locations = cells_data(columns = vars(length)) ) %>% tab_options( - stub_group.background.color = "#FFFFF0", + row_group.background.color = "#FFFFF0", column_labels.background.color = "#666660", - stub_group.font.weight = "600", stub_group.font.size = "smaller") %>% + row_group.font.weight = "600", + row_group.font.size = "smaller" + ) %>% tab_source_note(source_note = md( paste("The **paletteer** package is maintained by Emil Hvitfeldt. More information can be", "found on [the **paletteer** site](https://emilhvitfeldt.github.io/paletteer/) and", diff --git a/R/tab_options.R b/R/tab_options.R index 4e82501849..831af5a676 100644 --- a/R/tab_options.R +++ b/R/tab_options.R @@ -9,38 +9,38 @@ #' given in units of pixels. The \code{\link{px}()} and \code{\link{pct}()} #' helper functions can also be used to pass in numeric values and obtain #' values as pixel or percent units. -#' @param table.font.size,heading.title.font.size,heading.subtitle.font.size,column_labels.font.size,stub_group.font.size,footnote.font.size,sourcenote.font.size +#' @param table.font.size,heading.title.font.size,heading.subtitle.font.size,column_labels.font.size,row_group.font.size,footnote.font.size,sourcenote.font.size #' font sizes for the parent text element \code{table} and the following child #' elements: \code{heading.title}, \code{heading.subtitle}, \code{columns}, -#' \code{stub_group}, \code{footnote}, and \code{sourcenote}. Can be specified -#' as a single-length character vector with units of pixels -#' (e.g., \code{12px}) or as a percentage (e.g., \code{80\%}). If provided as a +#' \code{row_group}, \code{footnote}, and \code{sourcenote}. Can be specified +#' as a single-length character vector with units of pixels (e.g., +#' \code{12px}) or as a percentage (e.g., \code{80\%}). If provided as a #' single-length numeric vector, it is assumed that the value is given in #' units of pixels. The \code{\link{px}()} and \code{\link{pct}()} helper #' functions can also be used to pass in numeric values and obtain values as #' pixel or percent units. -#' @param column_labels.font.weight,stub_group.font.weight the font weight of -#' the \code{columns} and \code{stub_group} text element. +#' @param column_labels.font.weight,row_group.font.weight the font weight of +#' the \code{columns} and \code{row_group} text element. #' @param summary_row.text_transform,grand_summary_row.text_transform an option #' to apply text transformations to the label text in each summary row. -#' @param table.background.color,heading.background.color,column_labels.background.color,stub_group.background.color,summary_row.background.color,grand_summary_row.background.color +#' @param table.background.color,heading.background.color,column_labels.background.color,row_group.background.color,summary_row.background.color,grand_summary_row.background.color #' background colors for the parent element \code{table} and the following -#' child elements: \code{heading}, \code{columns}, \code{stub_group}, -#' \code{summary_row}, and \code{field}. A color name or a hexadecimal color -#' code should be provided. +#' child elements: \code{heading}, \code{columns}, \code{row_group}, +#' \code{summary_row}, and \code{table_body}. A color name or a hexadecimal +#' color code should be provided. #' @param table.border.top.style,table.border.top.width,table.border.top.color #' the style, width, and color of the table's top border. #' @param heading.border.bottom.style,heading.border.bottom.width,heading.border.bottom.color #' the style, width, and color of the heading's bottom border. -#' @param stub_group.border.top.style,stub_group.border.top.width,stub_group.border.top.color -#' the style, width, and color of the stub heading's top border. -#' @param stub_group.border.bottom.style,stub_group.border.bottom.width,stub_group.border.bottom.color -#' the style, width, and color of the stub heading's bottom border. -#' @param field.border.top.style,field.border.top.width,field.border.top.color -#' the style, width, and color of the field's top border. -#' @param field.border.bottom.style,field.border.bottom.width,field.border.bottom.color -#' the style, width, and color of the field's bottom border. -#' @param row.padding,summary_row.padding,grand_summary_row.padding the amount +#' @param row_group.border.top.style,row_group.border.top.width,row_group.border.top.color +#' the style, width, and color of the row group's top border. +#' @param row_group.border.bottom.style,row_group.border.bottom.width,row_group.border.bottom.color +#' the style, width, and color of the row group's bottom border. +#' @param table_body.border.top.style,table_body.border.top.width,table_body.border.top.color +#' the style, width, and color of the table body's top border. +#' @param table_body.border.bottom.style,table_body.border.bottom.width,table_body.border.bottom.color +#' the style, width, and color of the table body's bottom border. +#' @param row.padding,summary_row.padding,grand_summary_row.padding the amount #' of padding in each row and in each type of summary row. #' @param footnote.sep the separating characters between adjacent footnotes in #' the footnotes section. The default value produces a linebreak. @@ -56,8 +56,8 @@ #' the footnote and source note sections. #' @param row.striping.include_stub an option for whether to include the stub #' when striping rows. -#' @param row.striping.include_field an option for whether to include the field -#' when striping rows. +#' @param row.striping.include_table_body an option for whether to include the +#' table body when striping rows. #' @return an object of class \code{gt_tbl}. #' @examples #' # Use `exibble` to create a gt table with @@ -169,21 +169,21 @@ tab_options <- function(data, column_labels.background.color = NULL, column_labels.font.size = NULL, column_labels.font.weight = NULL, - stub_group.background.color = NULL, - stub_group.font.size = NULL, - stub_group.font.weight = NULL, - stub_group.border.top.style = NULL, - stub_group.border.top.width = NULL, - stub_group.border.top.color = NULL, - stub_group.border.bottom.style = NULL, - stub_group.border.bottom.width = NULL, - stub_group.border.bottom.color = NULL, - field.border.top.style = NULL, - field.border.top.width = NULL, - field.border.top.color = NULL, - field.border.bottom.style = NULL, - field.border.bottom.width = NULL, - field.border.bottom.color = NULL, + row_group.background.color = NULL, + row_group.font.size = NULL, + row_group.font.weight = NULL, + row_group.border.top.style = NULL, + row_group.border.top.width = NULL, + row_group.border.top.color = NULL, + row_group.border.bottom.style = NULL, + row_group.border.bottom.width = NULL, + row_group.border.bottom.color = NULL, + table_body.border.top.style = NULL, + table_body.border.top.width = NULL, + table_body.border.top.color = NULL, + table_body.border.bottom.style = NULL, + table_body.border.bottom.width = NULL, + table_body.border.bottom.color = NULL, row.padding = NULL, summary_row.background.color = NULL, summary_row.padding = NULL, @@ -198,7 +198,7 @@ tab_options <- function(data, sourcenote.font.size = NULL, sourcenote.padding = NULL, row.striping.include_stub = NULL, - row.striping.include_field = NULL) { + row.striping.include_table_body = NULL) { # Extract the `opts_df` data frame object from `data` opts_df <- attr(data, "opts_df", exact = TRUE) @@ -332,129 +332,129 @@ tab_options <- function(data, opts_df <- opts_df_set(opts_df, "column_labels_font_weight", column_labels.font.weight) } - # stub_group.background.color - if (!is.null(stub_group.background.color)) { + # row_group.background.color + if (!is.null(row_group.background.color)) { opts_df <- opts_df_set( - opts_df, "stub_group_background_color", stub_group.background.color) + opts_df, "row_group_background_color", row_group.background.color) } - # stub_group.font.size - if (!is.null(stub_group.font.size)) { + # row_group.font.size + if (!is.null(row_group.font.size)) { - if (is.numeric(stub_group.font.size)) { - stub_group.font.size <- paste0(stub_group.font.size, "px") + if (is.numeric(row_group.font.size)) { + row_group.font.size <- paste0(row_group.font.size, "px") } opts_df <- opts_df_set( - opts_df, "stub_group_font_size", stub_group.font.size) + opts_df, "row_group_font_size", row_group.font.size) } - # stub_group.font.weight - if (!is.null(stub_group.font.weight)) { + # row_group.font.weight + if (!is.null(row_group.font.weight)) { opts_df <- opts_df_set( - opts_df, "stub_group_font_weight", stub_group.font.weight) + opts_df, "row_group_font_weight", row_group.font.weight) } - # stub_group.border.top.style - if (!is.null(stub_group.border.top.style)) { + # row_group.border.top.style + if (!is.null(row_group.border.top.style)) { opts_df <- opts_df_set( - opts_df, "stub_group_border_top_style", stub_group.border.top.style) + opts_df, "row_group_border_top_style", row_group.border.top.style) } - # stub_group.border.top.width - if (!is.null(stub_group.border.top.width)) { + # row_group.border.top.width + if (!is.null(row_group.border.top.width)) { - if (is.numeric(stub_group.border.top.width)) { - stub_group.border.top.width <- paste0(stub_group.border.top.width, "px") + if (is.numeric(row_group.border.top.width)) { + row_group.border.top.width <- paste0(row_group.border.top.width, "px") } opts_df <- opts_df_set( - opts_df, "stub_group_border_top_width", stub_group.border.top.width) + opts_df, "row_group_border_top_width", row_group.border.top.width) } - # stub_group.border.top.color - if (!is.null(stub_group.border.top.color)) { + # row_group.border.top.color + if (!is.null(row_group.border.top.color)) { opts_df <- opts_df_set( - opts_df, "stub_group_border_top_color", stub_group.border.top.color) + opts_df, "row_group_border_top_color", row_group.border.top.color) } - # stub_group.border.bottom.style - if (!is.null(stub_group.border.bottom.style)) { + # row_group.border.bottom.style + if (!is.null(row_group.border.bottom.style)) { opts_df <- opts_df_set( - opts_df, "stub_group_border_bottom_style", stub_group.border.bottom.style) + opts_df, "row_group_border_bottom_style", row_group.border.bottom.style) } - # stub_group.border.bottom.width - if (!is.null(stub_group.border.bottom.width)) { + # row_group.border.bottom.width + if (!is.null(row_group.border.bottom.width)) { - if (is.numeric(stub_group.border.bottom.width)) { - stub_group.border.bottom.width <- paste0(stub_group.border.bottom.width, "px") + if (is.numeric(row_group.border.bottom.width)) { + row_group.border.bottom.width <- paste0(row_group.border.bottom.width, "px") } opts_df <- opts_df_set( - opts_df, "stub_group_border_bottom_width", stub_group.border.bottom.width) + opts_df, "row_group_border_bottom_width", row_group.border.bottom.width) } - # stub_group.border.bottom.color - if (!is.null(stub_group.border.bottom.color)) { + # row_group.border.bottom.color + if (!is.null(row_group.border.bottom.color)) { opts_df <- opts_df_set( - opts_df, "stub_group_border_bottom_color", stub_group.border.bottom.color) + opts_df, "row_group_border_bottom_color", row_group.border.bottom.color) } - # field.border.top.style - if (!is.null(field.border.top.style)) { + # table_body.border.top.style + if (!is.null(table_body.border.top.style)) { opts_df <- opts_df_set( - opts_df, "field_border_top_style", field.border.top.style) + opts_df, "table_body_border_top_style", table_body.border.top.style) } - # field.border.top.width - if (!is.null(field.border.top.width)) { + # table_body.border.top.width + if (!is.null(table_body.border.top.width)) { - if (is.numeric(field.border.top.width)) { - field.border.top.width <- paste0(field.border.top.width, "px") + if (is.numeric(table_body.border.top.width)) { + table_body.border.top.width <- paste0(table_body.border.top.width, "px") } opts_df <- opts_df_set( - opts_df, "field_border_top_width", field.border.top.width) + opts_df, "table_body_border_top_width", table_body.border.top.width) } - # field.border.top.color - if (!is.null(field.border.top.color)) { + # table_body.border.top.color + if (!is.null(table_body.border.top.color)) { opts_df <- opts_df_set( - opts_df, "field_border_top_color", field.border.top.color) + opts_df, "table_body_border_top_color", table_body.border.top.color) } - # field.border.bottom.style - if (!is.null(field.border.bottom.style)) { + # table_body.border.bottom.style + if (!is.null(table_body.border.bottom.style)) { opts_df <- opts_df_set( - opts_df, "field_border_bottom_style", field.border.bottom.style) + opts_df, "table_body_border_bottom_style", table_body.border.bottom.style) } - # field.border.bottom.width - if (!is.null(field.border.bottom.width)) { + # table_body.border.bottom.width + if (!is.null(table_body.border.bottom.width)) { - if (is.numeric(field.border.bottom.width)) { - field.border.bottom.width <- paste0(field.border.bottom.width, "px") + if (is.numeric(table_body.border.bottom.width)) { + table_body.border.bottom.width <- paste0(table_body.border.bottom.width, "px") } opts_df <- opts_df_set( - opts_df, "field_border_bottom_width", field.border.bottom.width) + opts_df, "table_body_border_bottom_width", table_body.border.bottom.width) } - # field.border.bottom.color - if (!is.null(field.border.bottom.color)) { + # table_body.border.bottom.color + if (!is.null(table_body.border.bottom.color)) { opts_df <- opts_df_set( - opts_df, "field_border_bottom_color", field.border.bottom.color) + opts_df, "table_body_border_bottom_color", table_body.border.bottom.color) } # row.padding @@ -577,11 +577,11 @@ tab_options <- function(data, opts_df, "row_striping_include_stub", row.striping.include_stub) } - # row.striping.include_field - if (!is.null(row.striping.include_field)) { + # row.striping.include_table_body + if (!is.null(row.striping.include_table_body)) { opts_df <- opts_df_set( - opts_df, "row_striping_include_field", row.striping.include_field) + opts_df, "row_striping_include_table_body", row.striping.include_table_body) } # Write the modified `opts_df` to the `data` attribute diff --git a/R/tab_style.R b/R/tab_style.R index 4e41c12fe8..9062b9dcd6 100644 --- a/R/tab_style.R +++ b/R/tab_style.R @@ -80,7 +80,6 @@ #' date <= "2015-12-15" #' ) %>% #' dplyr::select(-c(adj_close, volume)) %>% -#' dplyr::mutate(date = as.character(date)) %>% #' gt() %>% #' tab_style( #' style = cells_styles( diff --git a/R/utils.R b/R/utils.R index 09ad198fb8..8884a851cd 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,4 +1,5 @@ -# Create a tibble containing date formats +#' Create a tibble containing date formats +#' #' @importFrom dplyr tribble #' @noRd date_formats <- function() { @@ -21,7 +22,8 @@ date_formats <- function() { "14", "y.mn.day", "%y/%m/%d") } -# Create a tibble containing time formats +#' Create a tibble containing time formats +#' #' @importFrom dplyr tribble #' @noRd time_formats <- function() { @@ -35,7 +37,8 @@ time_formats <- function() { "5", "h_p", "%I %P") } -# Transform `date_style` to `date_format` +#' Transform a `date_style` to a `date_format` +#' #' @importFrom dplyr filter pull #' @noRd get_date_format <- function(date_style) { @@ -59,7 +62,8 @@ get_date_format <- function(date_style) { } } -# Transform `time_style` to `time_format` +#' Transform a `time_style` to a `time_format` +#' #' @importFrom dplyr filter pull #' @noRd get_time_format <- function(time_style) { @@ -83,18 +87,8 @@ get_time_format <- function(time_style) { } } -# Determine if a provided `currency` type is valid -#' @noRd -is_currency_valid <- function(currency) { - - ifelse( - as.character(currency) %in% currency_symbols$curr_symbol | - as.character(currency) %in% currencies$curr_code | - as.character(currency) %in% currencies$curr_number, - TRUE, FALSE) -} - -# Transform `currency` to currency string +#' Transform a `currency` code to a currency string +#' #' @importFrom dplyr filter pull #' @noRd get_currency_str <- function(currency, @@ -149,7 +143,8 @@ get_currency_str <- function(currency, } } -# Transform `currency` to a currency exponent +#' Get a currency exponent from a currency code +#' #' @importFrom dplyr filter pull #' @noRd get_currency_exponent <- function(currency) { @@ -179,39 +174,13 @@ get_currency_exponent <- function(currency) { } } -# Get the `sep_mark` value from a locale -#' @importFrom dplyr filter pull -#' @noRd -get_locale_sep_mark <- function(locale) { - - sep_mark <- - locales %>% - dplyr::filter(base_locale_id == locale) %>% - dplyr::pull(group_sep) - - sep_mark <- ifelse(sep_mark == "", " ", sep_mark) - - sep_mark -} - -# Get the `dec_mark` value from a locale -#' @importFrom dplyr filter pull -#' @noRd -get_locale_dec_mark <- function(locale) { - - dec_mark <- - locales %>% - dplyr::filter(base_locale_id == locale) %>% - dplyr::pull(dec_sep) - - dec_mark -} - -# This function processes input text based on the class; if incoming text has -# the class `from_markdown` (applied by the `md()` helper function), then the -# text will be sanitized and transformed to HTML from Markdown. If the incoming -# text has the class `html` (applied by `html()` helper function), then -# the text will be seen as HTML and it won't undergo sanitization +#' Process text based on rendering context any applied classes +#' +#' If the incoming text has the class `from_markdown` (applied by the `md()` +#' helper function), then the text will be sanitized and transformed to HTML +#' from Markdown. If the incoming text has the class `html` (applied by `html()` +#' helper function), then the text will be seen as HTML and it won't undergo +#' sanitization #' @importFrom stringr str_replace_all #' @importFrom htmltools htmlEscape #' @importFrom commonmark markdown_html @@ -305,8 +274,11 @@ process_text <- function(text, } } -# Find common HTML entities resulting from HTML escaping and -# restore them back to ascii characters +#' Reverse HTML escaping +#' +#' Find common HTML entities resulting from HTML escaping and restore them back +#' to ASCII characters +#' @noRd unescape_html <- function(text) { text %>% @@ -315,7 +287,8 @@ unescape_html <- function(text) { tidy_gsub("&", "&") } -#' Transform Markdown text to HTML; also performs HTML escaping +#' Transform Markdown text to HTML and also perform HTML escaping +#' #' @importFrom commonmark markdown_html #' @noRd md_to_html <- function(x) { @@ -331,8 +304,11 @@ md_to_html <- function(x) { x } -# Transform Markdown text to LaTeX; also escapes ASCII -# characters with special meaning in LaTeX +#' Transform Markdown text to LaTeX +#' +#' In addition to the Markdown-to-LaTeX text transformation, +#' `markdown_to_latex()` also escapes ASCII characters with special meaning in +#' LaTeX. #' @importFrom commonmark markdown_latex #' @noRd markdown_to_latex <- function(text) { @@ -360,7 +336,8 @@ markdown_to_latex <- function(text) { unname() } -# Transform Markdown text to plain text +#' Transform Markdown text to plain text +#' #' @importFrom commonmark markdown_text #' @noRd markdown_to_text <- function(text) { @@ -388,21 +365,36 @@ markdown_to_text <- function(text) { unname() } -# Get prepending and appending text based on a simple pattern -get_pre_post_txt <- function(pattern) { - - prefix <- strsplit(pattern, "\\{x\\}")[[1]][1] - suffix <- strsplit(pattern, "\\{x\\}")[[1]][2] - - prefix <- ifelse(is.na(prefix), "", prefix) - suffix <- ifelse(is.na(suffix), "", suffix) - - c(prefix, suffix) +#' Handle formatting of a pattern in a \code{fmt_*()} function +#' +#' Within the context of a \code{fmt_*()} function, we always have the +#' single-length character vector of \code{pattern} available to describe a +#' final decoration of the formatted values. We use \pkg{glue}'s semantics here +#' and reserve \code{x} to be the formatted values, and, we can use \code{x} +#' multiple times in the pattern. +#' @param pattern A formatting pattern that allows for decoration of the +#' formatted value (defined here as \code{x}). +#' @param values The values (as a character vector) that are formatted within +#' the \code{fmt_*()} function. +#' @noRd +apply_pattern_fmt_x <- function(pattern, + values) { + + vapply( + values, + function(x) tidy_gsub(x = pattern, "{x}", x, fixed = TRUE), + FUN.VALUE = character(1), + USE.NAMES = FALSE + ) } +#' Get a vector of indices for large-number suffixing +#' #' @importFrom utils head #' @noRd -non_na_index <- function(values, index, default_value = NA) { +non_na_index <- function(values, + index, + default_value = NA) { if (is.logical(index)) { index <- is.integer(index) @@ -445,7 +437,7 @@ non_na_index <- function(values, index, default_value = NA) { encoded$values <- ifelse( encoded$values == -Inf, - c(default_value, utils::head(encoded$values, -1)), + c(default_value, head(encoded$values, -1)), encoded$values ) @@ -456,16 +448,17 @@ non_na_index <- function(values, index, default_value = NA) { positions[index] } -# This function operates on a vector of numerical -# values and returns a tibble where each row -# represents a scaled values for `x` and the -# correct suffix to use during x's character-based -# formatting +#' Get a tibble of scaling values and suffixes +#' +#' The `num_suffix()` function operates on a vector of numerical values and +#' returns a tibble where each row represents a scaled value for `x` and the +#' correct suffix to use during `x`'s character-based formatting #' @importFrom dplyr tibble #' @noRd num_suffix <- function(x, suffixes = c("K", "M", "B", "T"), - base = 1000) { + base = 1000, + scale_by) { # If `suffixes` is a zero-length vector, we # provide a tibble that will ultimately not @@ -474,7 +467,7 @@ num_suffix <- function(x, return( dplyr::tibble( - scale_by = rep_len(1, length(x)), + scale_by = rep_len(scale_by, length(x)), suffix = rep_len("", length(x)) ) ) @@ -531,19 +524,28 @@ num_suffix <- function(x, ) } -# Create an `isFALSE`-based helper function that -# works with earlier versions of R (the `isFALSE()` -# function was introduced in R 3.5.0) +#' An `isFALSE`-based helper function +#' +#' The `is_false()` function is similar to the `isFALSE()` function that was +#' introduced in R 3.5.0 except that this implementation works with earlier +#' versions of R. +#' @param x The single value to test for whether it is `FALSE`. +#' @noRd is_false = function(x) { is.logical(x) && length(x) == 1L && !is.na(x) && !x } -# This function normalizes the `suffixing` input to a -# character vector which is later appended to scaled -# numerical values; the input can either be a single -# logical value or a character vector -normalize_suffixing_inputs <- function(suffixing) { +#' Normalize all suffixing input values +#' +#' This function normalizes the `suffixing` input to a character vector which is +#' later appended to scaled numerical values; the input can either be a single +#' logical value or a character vector +#' @param suffixing,scale_by The `suffixing` and `scale_by` options in some +#' `fmt_*()` functions. +#' @noRd +normalize_suffixing_inputs <- function(suffixing, + scale_by) { if (is_false(suffixing)) { @@ -554,16 +556,21 @@ normalize_suffixing_inputs <- function(suffixing) { } else if (isTRUE(suffixing)) { + # Issue a warning if `scale_by` is not 1.0 (the default) + warn_on_scale_by_input(scale_by) + # If `suffixing` is TRUE, return the default # set of suffixes return(c("K", "M", "B", "T")) } else if (is.character(suffixing)) { + # Issue a warning if `scale_by` is not 1.0 (the default) + warn_on_scale_by_input(scale_by) + # In the case that a character vector is provided # to `suffixing`, we first want to check if there # are any names provided - # TODO: found that the conditional below seems # better than other solutions to determine whether # the vector is even partially named @@ -588,7 +595,22 @@ normalize_suffixing_inputs <- function(suffixing) { } } -# Derive a label based on a formula or a function name +#' If performing large-number suffixing, warn on `scale_by` != 1 +#' +#' @param scale_by The `scale_by` option in some `fmt_*()` functions. +#' @noRd +warn_on_scale_by_input <- function(scale_by) { + + if (scale_by != 1) { + warning("The value for `scale_by` cannot be changed if `suffixing` is ", + "anything other than `FALSE`. The value provided to `scale_by` ", + "will be ignored.", + call. = FALSE) + } +} + +#' Derive a label based on a formula or a function name +#' #' @import rlang #' @noRd derive_summary_label <- function(fn) { @@ -612,21 +634,25 @@ derive_summary_label <- function(fn) { } #nocov start - -# This function is a conveient wrapper for `system.file()` where the `package` -# refers to this package +#' A `system.file()` replacement specific to this package +#' +#' This is a conveient wrapper for `system.file()` where the `package` refers to +#' this package. +#' @noRd system_file <- function(file) { system.file(file, package = "gt") } - #nocov end -# This function removes entire HTML tags from input text +#' Remove all HTML tags from input text +#' +#' @noRd remove_html <- function(text) { gsub("<.+?>", "", text) } -# This function transforms a CSS stylesheet to a tibble representation +#' Transform a CSS stylesheet to a tibble representation +#' #' @importFrom dplyr bind_rows tibble filter mutate case_when select pull #' @importFrom stringr str_remove str_extract str_trim str_detect #' @noRd @@ -683,7 +709,8 @@ get_css_tbl <- function(data) { css_tbl } -# Create an inlined style block from a CSS tibble +#' Create an inlined style block from a CSS tibble +#' #' @importFrom dplyr filter select distinct mutate pull #' @importFrom stringr str_split #' @noRd @@ -709,7 +736,8 @@ create_inline_styles <- function(class_names, "\"") } -# Transform HTML to inlined HTML using a CSS tibble +#' Transform HTML to inlined HTML using a CSS tibble +#' #' @importFrom stringr str_extract str_replace str_match #' @noRd inline_html_styles <- function(html, css_tbl) { @@ -776,6 +804,11 @@ inline_html_styles <- function(html, css_tbl) { html } +#' Split any strings that are values in scientific notation +#' +#' @param x_str The input character vector of values formatted in scientific +#' notation. +#' @noRd split_scientific_notn <- function(x_str) { exp_parts <- strsplit(x_str, "e|E") @@ -785,14 +818,25 @@ split_scientific_notn <- function(x_str) { list(num = num_part, exp = exp_part) } -# This function is wrapper for `gsub()` that uses default argument values and -# rearranges first three arguments for better pipelining -tidy_gsub <- function(x, pattern, replacement) { +#' Wrapper for `gsub()` where `x` is the first argument +#' +#' This function is wrapper for `gsub()` that uses default argument values and +#' rearranges first three arguments for better pipelining +#' @param x,pattern,replacement,fixed Select arguments from the `gsub()` +#' function. +#' @noRd +tidy_gsub <- function(x, pattern, replacement, fixed = FALSE) { - gsub(pattern, replacement, x) + gsub(pattern, replacement, x, fixed = fixed) } -# Options setter for the `opts_df` data frame +#' An options setter for the `opts_df` data frame +#' +#' @param opts_df The `opts_df` data frame. +#' @param option The option name; a unique value in the `parameter` column of +#' `opts_df`. +#' @param value The value to set for the given `option`. +#' @noRd opts_df_set <- function(opts_df, option, value) { opts_df[which(opts_df$parameter == option), "value"] <- value @@ -800,13 +844,21 @@ opts_df_set <- function(opts_df, option, value) { opts_df } -# Options getter for the `opts_df` data frame +#' An options getter for the `opts_df` data frame +#' +#' @inheritParams opts_df_set +#' @noRd opts_df_get <- function(opts_df, option) { opts_df[which(opts_df$parameter == option), "value"] } -# Upgrade `cells_*()` to a list() if a single instance provided +#' Upgrader function for `cells_*` objects +#' +#' Upgrade a `cells_*` object to a `list()` if only a single instance is +#' provided. +#' @param locations Any `cells_*` object. +#' @noRd as_locations <- function(locations) { if (!inherits(locations, "location_cells")) { @@ -824,6 +876,9 @@ as_locations <- function(locations) { locations } +#' Create a vector of glyphs to use for footnotes +#' +#' @noRd footnote_glyphs <- function(x, glyphs) { @@ -849,9 +904,14 @@ footnote_glyphs <- function(x, glyphs_val, glyphs_rep, FUN = function(val_i, rep_i) { paste(rep(val_i, rep_i), collapse = "")} - ) %>% unname() + ) %>% + unname() } +#' Determine whether an object is a `gt_tbl` +#' +#' @param data A table object that is created using the \code{\link{gt}()} +#' function. #' @importFrom checkmate test_class #' @noRd is_gt <- function(data) { @@ -859,6 +919,11 @@ is_gt <- function(data) { checkmate::test_class(data, "gt_tbl") } +#' Stop any function if object is not a `gt_tbl` object +#' +#' @param data A table object that is created using the \code{\link{gt}()} +#' function. +#' @noRd stop_if_not_gt <- function(data) { if (!is_gt(data)) { diff --git a/R/utils_formatters.R b/R/utils_formatters.R new file mode 100644 index 0000000000..99c548b363 --- /dev/null +++ b/R/utils_formatters.R @@ -0,0 +1,369 @@ +#' Filter an internal table to a single row with filtering expressions +#' +#' @param table The table to filter down to one row. +#' @param column The column from which the single value should be obtained. +#' @param ... The arguments passed to `dplyr::filter()` +#' @import rlang +#' @importFrom dplyr filter +#' @noRd +filter_table_to_value <- function(table, column, ...) { + + filter_args_enquos <- rlang::enquos(...) + column_enquo <- rlang::enquo(column) + + filtered_tbl <- dplyr::filter(table, !!!filter_args_enquos) + + if (nrow(filtered_tbl) != 1) { + stop("Internal error in `gt:::filter_table_to_row()`:\n", + " * The filtered table doesn't result in a table of exactly one row. ", + "Found ", nrow(filtered_tbl), " rows.", + call. = FALSE) + } + + filtered_tbl %>% + dplyr::pull(!!column_enquo) +} + +#' Validate the user-supplied `locale` value +#' +#' @param locale The user-supplied `locale` value, found in several `fmt_*()` +#' functions. This is expected as `NULL` if not supplied by the user. +#' @noRd +validate_locale <- function(locale) { + + # Stop function if the `locale` provided + # isn't a valid one + if (!(locale %in% locales$base_locale_id)) { + stop("The supplied `locale` is not available in the list of supported locales.\n", + " * Use the `info_locales()` function to see which locales can be used.", + call. = FALSE) + } +} + +#' Validate the user-supplied `currency` value +#' +#' @param currency The user-supplied `currency` value, found in the +#' `fmt_currency()` function. +#' @noRd +validate_currency <- function(currency) { + + # Stop function if the `currency` provided + # isn't a valid one + if (!( + as.character(currency) %in% currency_symbols$curr_symbol | + as.character(currency) %in% currencies$curr_code | + as.character(currency) %in% currencies$curr_number)) { + stop("The supplied `currency` is not available in the list of supported currencies.\n", + " * Use the `info_currencies()` function to see which currencies can be used.\n", + " * See `?fmt_currency` to understand which input types are valid.", + call. = FALSE) + } +} + +#' Get the `sep_mark` value based on a locale +#' +#' @param locale The user-supplied `locale` value, found in several `fmt_*()` +#' functions. This is expected as `NULL` if not supplied by the user. +#' @param default The default value for the `sep_mark`. +#' @param use_seps A logical value for whether to use separators at all. +#' @importFrom dplyr filter pull +#' @noRd +get_locale_sep_mark <- function(locale = NULL, + default, + use_seps) { + + # If `use_seps` is FALSE, then force + # `sep_mark` to be an empty string + if (!use_seps) { + return("") + } + + # If `locale` is NULL then return the + # default `sep_mark` + if (is.null(locale)) { + return(default) + } + + # Stop function if the `locale` provided + # isn't a valid one + validate_locale(locale) + + # Get the correct `group_sep` value from the + # `gt:::locales` lookup table + sep_mark <- + filter_table_to_value(locales, group_sep, base_locale_id == locale) + + # TODO: Modify `locales` table to replace `""` with + # `" "` in `group_sep` column; once that is done, the + # below statement can be safely removed + if (sep_mark == "") sep_mark <- " " + + sep_mark +} + +#' Get the `dec_mark` value based on a locale +#' +#' @param locale The user-supplied `locale` value, found in several `fmt_*()` +#' functions. This is expected as `NULL` if not supplied by the user. +#' @param default The default value for the `dec_mark`. +#' @importFrom dplyr filter pull +#' @noRd +get_locale_dec_mark <- function(locale = NULL, + default) { + + # If `locale` is NULL then return the + # default `dec_mark` + if (is.null(locale)) { + return(default) + } + + # Stop function if the `locale` provided + # isn't a valid one + validate_locale(locale) + + # Get the correct `dec_sep` value from the + # `gt:::locales` lookup table + filter_table_to_value(locales, dec_sep, base_locale_id == locale) +} + +#' Determine which numbers in scientific notation would be zero order +#' +#' @param x A vector of numeric values, including `NA` values +#' @noRd +has_order_zero <- function(x) { + + ( + (x >= 1 & x < 10) | (x <= -1 & x > -10) | x == 0 + ) & !is.na(x) +} + +#' @noRd +get_currency_decimals <- function(currency, + decimals, + use_subunits) { + + # Get the number of decimal places + if (is.null(decimals) && use_subunits) { + + # Get decimal places using `get_currency_exponent()` fcn + if (currency %in% currency_symbols$curr_symbol) { + + return(2) + + } else { + + return(get_currency_exponent(currency)) + } + + } else if (is.null(decimals) && !use_subunits) { + + return(0) + + } else { + return(decimals) + } +} + +#' Apply a scaling factor to a vector of numeric values +#' +#' @param x A vector of numeric values. +#' @param scale_by A numeric scalar. +#' @noRd +scale_x_values <- function(x, + scale_by) { + checkmate::assert_numeric( + scale_by, + finite = TRUE, + any.missing = FALSE) + + len <- length(scale_by) + + # Stop function if the length of `scale_by` + # is not 1 of the length of `x` + if (!any(len == 1, len == length(x))) { + stop("The length of the `scale_by` vector must be 1 or the length of `x`.", + call. = FALSE) + } + + x * scale_by +} + +#' A `formatC()` call for `fmt_number()` and `fmt_percent()` +#' +#' @param x A vector of numeric values. +#' @param decimals The number of decimal places (`digits`). +#' @param sep_mark The separator for number groups (`big.mark`). +#' @param dec_mark The decimal separator mark (`decimal.mark`). +#' @param format The numeric format for `formatC()`. +#' @param drop_trailing_zeros Option to exclude trailing decimal zeros. +#' @noRd +format_num_to_str <- function(x, + decimals, + sep_mark, + dec_mark, + drop_trailing_zeros, + format = "f") { + + formatC( + x = x, + digits = decimals, + mode = "double", + big.mark = sep_mark, + decimal.mark = dec_mark, + format = format, + drop0trailing = drop_trailing_zeros + ) +} + +#' A `formatC()` call for `fmt_scientific()` +#' +#' @inheritParams format_num_to_str +#' @noRd +format_num_to_str_e <- function(x, + decimals, + sep_mark, + dec_mark, + drop_trailing_zeros) { + + format_num_to_str( + x, + decimals, + sep_mark, + dec_mark, + format = "e", + drop_trailing_zeros) +} + +#' A `formatC()` call for `fmt_currency()` +#' +#' @inheritParams format_num_to_str +#' @noRd +format_num_to_str_c <- function(x, + decimals, + sep_mark, + dec_mark) { + + format_num_to_str( + x, + decimals, + sep_mark, + dec_mark, + format = "f", + drop_trailing_zeros = FALSE) +} + +#' Surround formatted values with `$`s for LaTeX +#' +#' @noRd +to_latex_math_mode <- function (x) { + + x %>% + paste_between(x_2 = c("$", "$")) +} + +context_minus_mark <- function(context) { + + switch(context, + html = "−", + "-") +} + +context_negative_currency_mark <- function(context) { + + switch(context, + html = "−", + "-") +} + +context_parens_marks <- function(context) { + + switch(context, + html = c("(", ")"), + latex = c("\\left(", "\\right)"), + c("(", ")")) +} + +context_parens_marks_number <- function(context) { + + switch(context, + html = c("(", ")"), + latex = c("(", ")"), + c("(", ")")) +} + +context_exp_marks <- function(context) { + + switch(context, + html = c(" × 10", ""), + latex = c(" \\times 10^{", "}"), + c(" x 10(", ")")) +} + +context_percent_mark <- function(context) { + + switch(context, + html = "%", + latex = "\\%", + "%") +} + +context_currency_str_regex <- function(context) { + + switch(context, + latex = "\\\\$", + "\\$") +} + +context_currency_str <- function(context, currency) { + + switch(context, + html = { + get_currency_str(currency) + }, + latex = { + currency %>% + get_currency_str(fallback_to_code = TRUE) %>% + markdown_to_latex() %>% + paste_between(x_2 = c("\\text{", "}")) + }, + { + currency %>% + get_currency_str(fallback_to_code = TRUE) + }) +} + +paste_currency_str <- function(x, + currency_str, + incl_space, + placement) { + + vapply(FUN.VALUE = character(1), USE.NAMES = FALSE, x, function(x) { + + if (grepl("^-", x)) { + + x %>% + tidy_gsub("^-", "") %>% + paste_on_side( + x_side = ifelse(incl_space, " ", ""), + direction = placement + ) %>% + paste_on_side( + x_side = currency_str, + direction = placement + ) %>% + paste_left("-") + + } else { + + x %>% + paste_on_side( + x_side = ifelse(incl_space, " ", ""), + direction = placement + ) %>% + paste_on_side( + x_side = currency_str, + direction = placement + ) + } + }) +} diff --git a/R/utils_general_str_formatting.R b/R/utils_general_str_formatting.R new file mode 100644 index 0000000000..d35dfde4c8 --- /dev/null +++ b/R/utils_general_str_formatting.R @@ -0,0 +1,317 @@ +###### +# General String Formatters +###### + +#' Flexibly split a string into two pieces +#' +#' @param x The string to split into a character vector of length 2. +#' @param before,after Either an exact numeric position for where splitting will +#' occur, or a regular expression to match on a range of characters. We can +#' use either `before` or `after` (but not both) with this variable input to +#' accurately define which side of the match is the split position. +#' @noRd +split_string_2 <- function(x, + before = NULL, + after = NULL) { + + # Stop function if `x` is not of class character + if (!inherits(x, "character")) { + stop("Internal error in `gt:::paste_within()`:\n", + "* The `x` object must be of class character.", + call. = FALSE) + } + + # Stop function if the length of `x` is not 1 + if (length(x) != 1) { + stop("Internal error in `gt:::paste_within()`:\n", + "* The length of the `x` must be exactly 1.", + call. = FALSE) + } + + # Get the length of the string `x` + x_length <- nchar(x) + + # If neither of `before` or `after` has a value, + # stop the function + if (is.null(before) && is.null(after)) { + stop("Internal error in `gt:::split_string_2()`:\n", + " * Both `before` and `after` cannot be `NULL`.", + call. = FALSE) + } + + # If both `before` and `after` have values, stop + # the function + if (!is.null(before) && !is.null(after)) { + stop("Internal error in `gt:::split_string_2()`:\n", + " * A value must be provided to either `before` or `after`, not both.", + call. = FALSE) + } + + # Collapse value for either `before` or `after`; + # add a class to retain the direction-of-split + # information + if (!is.null(before)) { + input <- before + class(input) <- c("before", class(before)) + } else if (!is.null(after)) { + input <- after + class(input) <- c("after", class(after)) + } + + if (inherits(input, "character")) { + + # Use the pattern (`input`) with the input string + # `x` with `regexpr()` to get the matching output + regexpr_out <- regexpr(input, x) + + # If there is no match, return a character vector + # of length 2 (original string, then empty string) + if (as.numeric(regexpr_out) == -1) { + return(c(x, "")) + } + + # Define the start position for the matched characters + split_start <- + regexpr_out %>% + as.numeric() + + # Define the stop position for the matched characters + split_stop <- + attr(regexpr_out, "match.length", exact = TRUE) + split_start - 1 + + } else if (inherits(input, "numeric")) { + + # Stop function if the index position is not valid + if (input > x_length) { + stop("Internal error in `gt:::split_string_2()`:\n", + "* The numeric value provided cannot be greater than ", x_length, ".", + call. = FALSE) + } + + # Define the start and stop positions as + # the single `input` value + split_start <- split_stop <- input %>% as.numeric() + } + + # Perform the split either before the matched characters + if (inherits(input, "before")) { + + x_2 <- c(substr(x, 0, split_start - 1), substr(x, split_start, x_length)) + + } else if (inherits(input, "after")) { + + x_2 <- c(substr(x, 0, split_stop), substr(x, split_stop + 1, x_length)) + } + + x_2 +} + +#' Flexibly split a string into two pieces +#' +#' @param x A character vector that is to be pasted between the +#' first and second elements of `x_2`. +#' @param x_2 A character vector of length 2. +#' @noRd +paste_between <- function(x, + x_2) { + + # Stop function if `x_2` is not of class character + if (!inherits(x_2, "character")) { + stop("Internal error in `gt:::paste_between()`:\n", + "* The `x_2` object must be of class character.", + call. = FALSE) + } + + # Stop function if the length of `x_2` is not 2 + if (length(x_2) != 2) { + stop("Internal error in `gt:::paste_between()`:\n", + "* The length of the `x_2` must be exactly 2.", + call. = FALSE) + } + + # Stop function if `x` is not of class character + if (!inherits(x, "character")) { + stop("Internal error in `gt:::paste_between()`:\n", + "* The `x` object must be of class character.", + call. = FALSE) + } + + paste0(x_2[1], x, x_2[2]) +} + +#' Paste a string either onto the left or the right of another string +#' +#' @param x A character vector of length equal to that of `x_side`. +#' @param x_side Another character vector, with a length equal to that of `x`. +#' It will be pasted either to the left or to the right of `x` depending on +#' the `direction`. +#' @param direction The side that `x_side` will be relative to `x`. This can +#' be `left` or `right`. +#' @noRd +paste_on_side <- function(x, + x_side, + direction) { + + # Stop function if `direction` is not valid + if (!(direction %in% c("left", "right"))) { + stop("Internal error in `gt:::paste_on_side()`:\n", + "* The `direction` must be either `left` or `right`.", + call. = FALSE) + } + + # Stop function if `x` and `x_side` are not both of class character + if (any(!inherits(x, "character"), !inherits(x_side, "character"))) { + stop("Internal error in `gt:::paste_on_side()`:\n", + "* The `x` and `x_side` objects must be of class character.", + call. = FALSE) + } + + len <- length(x_side) + + # Stop function if the length of `x_side` is not 1 of the length of `x` + if (!any(len == 1, len == length(x))) { + stop("The length of the `x_side` vector must be 1 or the length of `x`.", + call. = FALSE) + } + + if (direction == "left") { + + return(paste0(x_side, x)) + + } else if (direction == "right") { + + return(paste0(x, x_side)) + } +} + +#' Paste a string onto the left side of another string +#' +#' @inheritParams paste_on_side +#' @param x_left Another character vector of length 1 that is to be pasted to +#' the left of `x`. +#' @noRd +paste_left <- function(x, x_left) { + paste_on_side(x, x_side = x_left, direction = "left") +} + +#' Paste a string onto the right side of another string +#' +#' @inheritParams paste_on_side +#' @param x_right Another character vector of length 1 that is to be pasted to +#' the right of `x`. +#' @noRd +paste_right <- function(x, x_right) { + paste_on_side(x, x_side = x_right, direction = "right") +} + +#' Swap adjacent text groups +#' +#' @param x A text string. +#' @param pattern_1,pattern_2 Regular expression to match on a range of +#' characters. The order of regex patterns does not need to be in the order of +#' matching in `x`. +#' @noRd +swap_adjacent_text_groups <- function(x, + pattern_1, + pattern_2) { + + # Stop function if `x` is not of class character + if (!inherits(x, "character")) { + stop("Internal error in `gt:::paste_within()`:\n", + "* The `x` object must be of class character.", + call. = FALSE) + } + + vapply(x, function(x) { + + # Return `x` as is if both patterns aren't present + if (is_false(grepl(pattern_1, x)) || is_false(grepl(pattern_2, x))) { + return(x) + } + + # Get the start and stop positions for the text groups + group_1 <- x %>% get_start_stop_positions(pattern = pattern_1) + group_2 <- x %>% get_start_stop_positions(pattern = pattern_2) + + # Return `x` as is if the patterns don't encompass text ranges + # that aren't adjacent + if (!is_adjacent_separate(group_1, group_2)) { + return(x) + } + + # Obtain a length-two vector of text groups based on the + # extracted substrings + substr <- + c( + substring(x, group_1[1], group_1[2]), + substring(x, group_2[1], group_2[2]) + ) + + # Reverse the order of the elements in `substr` + # if necessary and paste elements together + if (group_1[1] < group_2[1]) { + rev_group <- paste0(rev(substr), collapse = "") + } else { + rev_group <- paste0(substr, collapse = "") + } + + # Get the character indices that the contiguous text + # groups encompass + group_pos <- min(group_1, group_2):max(group_1, group_2) + + # Return the reversed set of patterns + paste0( + substring(x, 0, min(group_pos) - 1), + rev_group, + substring(x, max(group_pos) + 1, nchar(x)), + collapse = "" + ) + }, + FUN.VALUE = character(1), + USE.NAMES = FALSE + ) +} + +#' Get the start and stop positions for a text match +#' +#' @param x A text string. +#' @param pattern A regular expression pattern. +#' @noRd +get_start_stop_positions <- function(x, + pattern) { + + # Use the pattern (`input`) with the input string + # `x` with `regexpr()` to get the matching output + regexpr_out <- regexpr(pattern, x) + + # Define the start position for the matched characters + start_pos <- regexpr_out %>% as.numeric() + + # Define the stop position for the matched characters + stop_pos <- attr(regexpr_out, "match.length", exact = TRUE) + start_pos - 1 + + # Return a vector of length 2 + c(start_pos, stop_pos) +} + +#' Determine if text groups are adjacent and non-overlapping +#' +#' @param group_1,group_2 Vectors of length 2 with starting and stopping +#' positions in a text string. +#' @noRd +is_adjacent_separate <- function(group_1, + group_2) { + + group_1_expanded <- seq(group_1[1], group_1[2]) + group_2_expanded <- seq(group_2[1], group_2[2]) + + if (length(base::intersect(group_1_expanded, group_2_expanded)) > 0) { + return(FALSE) + } + + if (any(diff(sort(c(group_1_expanded, group_2_expanded))) > 1)) { + return(FALSE) + } + + return(TRUE) +} diff --git a/R/utils_render_common.R b/R/utils_render_common.R index a6df42efd2..5d636bb6b6 100644 --- a/R/utils_render_common.R +++ b/R/utils_render_common.R @@ -400,7 +400,7 @@ create_summary_dfs <- function(summary_list, # Resolve the columns to exclude columns_excl <- base::setdiff(colnames(output_df), columns) - # Combine `groupname` with the field data in order to + # Combine `groupname` with the table body data in order to # process data by groups if (groups[1] != "::GRAND_SUMMARY") { @@ -737,7 +737,7 @@ process_source_notes <- function(source_note, context) { } } -# Function to build a vector of `group` rows in the table field +# Function to build a vector of `group` rows in the table body create_group_rows <- function(n_rows, groups_rows_df, context = "latex") { @@ -760,7 +760,7 @@ create_group_rows <- function(n_rows, unname() } -# Function to build a vector of `data` rows in the table field +# Function to build a vector of `data` rows in the table body create_data_rows <- function(n_rows, row_splits, context = "latex") { @@ -777,7 +777,7 @@ create_data_rows <- function(n_rows, unname() } -# Function to build a vector of `summary` rows in the table field +# Function to build a vector of `summary` rows in the table body create_summary_rows <- function(n_rows, n_cols, list_of_summaries, diff --git a/R/utils_render_html.R b/R/utils_render_html.R index 6f4ebbfcf3..d44008c7c4 100644 --- a/R/utils_render_html.R +++ b/R/utils_render_html.R @@ -1,9 +1,14 @@ -# Transform a footnote glyph to an HTML representation as a superscript + +#' Transform a footnote glyph to an HTML representation +#' +#' @noRd footnote_glyph_to_html <- function(footnote_glyph) { paste0("", footnote_glyph, "") } +#' Get the spanner column label style from an attribute table +#' #' @importFrom dplyr filter pull #' @noRd get_spanner_style <- function(spanner_style_attrs, @@ -23,6 +28,8 @@ get_spanner_style <- function(spanner_style_attrs, } } +#' Get the column label style from an attribute table +#' #' @importFrom dplyr filter pull #' @noRd get_column_style <- function(column_style_attrs, @@ -42,6 +49,9 @@ get_column_style <- function(column_style_attrs, } } +#' Create a set of inline style attributes +#' +#' @noRd create_style_attrs <- function(style_values) { style_rules <- c() @@ -58,15 +68,19 @@ create_style_attrs <- function(style_values) { style_rules } -# Taking the `body_content` vector, split into list components with one -# item per row in the output table +#' Split the body content vector into a list structure +#' +#' Taking the `body_content` vector, split into list components with one item +#' per row in the output table +#' @noRd split_body_content <- function(body_content, n_cols) { split(body_content, ceiling(seq_along(body_content) / n_cols)) } -# Apply footnotes to the data rows +#' Apply footnotes to the data rows +#' #' @importFrom dplyr filter group_by mutate ungroup select distinct #' @noRd apply_styles_to_output <- function(output_df, @@ -113,7 +127,8 @@ apply_styles_to_output <- function(output_df, split_body_content(body_content = body_styles, n_cols) } -#' Apply styles to summary rows +#' Apply footnotes to the summary data cells +#' #' @importFrom dplyr filter group_by mutate ungroup select distinct #' @noRd apply_styles_to_summary_output <- function(summary_df, @@ -204,9 +219,11 @@ create_table_start_h <- function(groups_rows_df) { "\n
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
-We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
-Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
-Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
-Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
-This Code of Conduct is adapted from the Contributor Covenant (http://contributor-covenant.org), version 1.0.0, available at http://contributor-covenant.org/version/1/0/0/
-There are many ways to contribute to the ongoing development of the gt package. Some contributions can be rather easy to do (e.g., fixing typos, improving documentation, filing issues for feature requests or problems, etc.) whereas other contributions can require more time and patience (like answering questions and submitting pull requests with code changes). Just know that that help provided in any capacity is very much appreciated. :)
-If you believe you found a bug, create a minimal reprex for your posting to the gt issue tracker. Try not to include anything unnecessary, just the minimal amount of code that constitutes the reproducible bug. We will try to verify the bug by running the code in the reprex provided. The quality of the reprex will reduce the amount of back-and-forth communication in trying to understand how to execute the code on our systems.
-A great way to help is by simply answering questions. Itās amazing how a little conversation could lead to better insights on a problem. Donāt quite know the answer? Thatās okay too. Weāre all in this together.
-Where might you answer user questions? Some of the forums for Q&A on gt include the RStudio community, on Twitter (a good search term is gt #rstats
), and on Stack Overflow. Good etiquette is key during these interactions: be a good person to all who ask questions.
Should you consider making a pull request (PR), please file an issue first and explain the problem in some detail. If the PR is an enhancement, detail how the change would make things better for package users. Bugfix PRs also requre some explanation about the bug and how the proposed fix will remove that bug. A great way to illustrate the bug is to include a reprex. While all this upfront work prior to preparing a PR can be time-consuming it opens a line of communication with the package authors and the community, perhaps leading to better enhancement or more effective fixes!
-Once there is consensus that a PR based on the issue would be helpful, adhering to the following process will make things proceed more quickly:
-.Rd
files in the man
folder).NEWS.md
below the current development version header describing any user-facing changes made; include your GitHub username, and links to relevant issue(s)/PR(s).Please briefly describe your problem or your ideas for enhancement in the template below.
-Have a question? Please donāt use this form but instead ask on RStudio community, on Stack Overflow, or on Twitter (using the #rstats
hashtag).
When describing a bug, please include a minimal reproducible example (otherwise known as a reprex).
-When posting, delete these explanatory lines and submit only the text derived from the template below.
-YEAR: 2018 -COPYRIGHT HOLDER: RStudio, Inc -ORGANIZATION: RStudio, Inc -- -
The MIT License (MIT)
-Copyright (c) 2018 RStudio, Inc
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the āSoftwareā), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED āAS ISā, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- - -
-
Letās make a display table using the gtcars
dataset. We all know mtcars
ā¦ what is gtcars
? Itās basically a modernized mtcars
for the gt age. Itās part of the gt package, and here is a preview of the tibble:
# This is `gtcars`
-dplyr::glimpse(gtcars)
-#> Observations: 47
-#> Variables: 15
-#> $ mfr <chr> "Ford", "Ferrari", "Ferrari", "Ferrari", "Ferrari", ā¦
-#> $ model <chr> "GT", "458 Speciale", "458 Spider", "458 Italia", "4ā¦
-#> $ year <dbl> 2017, 2015, 2015, 2014, 2016, 2015, 2017, 2015, 2015ā¦
-#> $ trim <chr> "Base Coupe", "Base Coupe", "Base", "Base Coupe", "Bā¦
-#> $ bdy_style <chr> "coupe", "coupe", "convertible", "coupe", "coupe", "ā¦
-#> $ hp <dbl> 647, 597, 562, 562, 661, 553, 680, 652, 731, 949, 57ā¦
-#> $ hp_rpm <dbl> 6250, 9000, 9000, 9000, 8000, 7500, 8250, 8000, 8250ā¦
-#> $ trq <dbl> 550, 398, 398, 398, 561, 557, 514, 504, 509, 664, 47ā¦
-#> $ trq_rpm <dbl> 5900, 6000, 6000, 6000, 3000, 4750, 5750, 6000, 6000ā¦
-#> $ mpg_c <dbl> 11, 13, 13, 13, 15, 16, 12, 11, 11, 12, 21, 16, 11, ā¦
-#> $ mpg_h <dbl> 18, 17, 17, 17, 22, 23, 17, 16, 16, 16, 22, 22, 18, ā¦
-#> $ drivetrain <chr> "rwd", "rwd", "rwd", "rwd", "rwd", "rwd", "awd", "awā¦
-#> $ trsmn <chr> "7a", "7a", "7a", "7a", "7a", "7a", "7a", "7a", "7a"ā¦
-#> $ ctry_origin <chr> "United States", "Italy", "Italy", "Italy", "Italy",ā¦
-#> $ msrp <dbl> 447000, 291744, 263553, 233509, 245400, 198973, 2980ā¦
For the purpose of simply learning more about gt, letās reduce this 47-row tibble to one that has only 8 rows:
-# Get a subset of 8 cars from the `gtcars` dataset: two
-# from each manufacturer country of origin except the UK
-gtcars_8 <-
- gtcars %>%
- dplyr::group_by(ctry_origin) %>%
- dplyr::top_n(2) %>%
- dplyr::ungroup() %>%
- dplyr::filter(ctry_origin != "United Kingdom")
-#> Selecting by msrp
-
-# Show the `gtcars_8` tibble
-dplyr::glimpse(gtcars_8)
-#> Observations: 8
-#> Variables: 15
-#> $ mfr <chr> "Ford", "Ferrari", "Acura", "Nissan", "Lamborghini",ā¦
-#> $ model <chr> "GT", "LaFerrari", "NSX", "GT-R", "Aventador", "i8",ā¦
-#> $ year <dbl> 2017, 2015, 2017, 2016, 2015, 2016, 2017, 2016
-#> $ trim <chr> "Base Coupe", "Base Coupe", "Base Coupe", "Premium Cā¦
-#> $ bdy_style <chr> "coupe", "coupe", "coupe", "coupe", "coupe", "coupe"ā¦
-#> $ hp <dbl> 647, 949, 573, 545, 700, 357, 645, 503
-#> $ hp_rpm <dbl> 6250, 9000, 6500, 6400, 8250, 5800, 5000, 6250
-#> $ trq <dbl> 550, 664, 476, 436, 507, 420, 600, 479
-#> $ trq_rpm <dbl> 5900, 6750, 2000, 3200, 5500, 3700, 5000, 1750
-#> $ mpg_c <dbl> 11, 12, 21, 16, 11, 28, 12, 16
-#> $ mpg_h <dbl> 18, 16, 22, 22, 18, 29, 19, 22
-#> $ drivetrain <chr> "rwd", "rwd", "awd", "awd", "awd", "awd", "rwd", "rwā¦
-#> $ trsmn <chr> "7a", "7a", "9a", "6a", "7a", "6am", "6m", "7a"
-#> $ ctry_origin <chr> "United States", "Italy", "Japan", "Japan", "Italy",ā¦
-#> $ msrp <dbl> 447000, 1416362, 156000, 101770, 397500, 140700, 958ā¦
Letās make a display table from this dataset. In doing so weāll fulfill the following 10 requirements:
-trsmn
) codes so that they are readable and understandableLetās again use dplyr to help make groupings by the ctry_origin
column, which provides the country of origin for the vehicle manufacturer of the car. We can simply use dplyr::group_by()
on the gtcars
dataset and pass that to gt()
. What you get is a display table that arranges the cars into row groups, with the name of the group displayed prominently above.
# Use `group_by()` on `gtcars` and pass that to `gt()`
-gtcars_8 %>%
- dplyr::group_by(ctry_origin) %>%
- gt()
mfr | -model | -year | -trim | -bdy_style | -hp | -hp_rpm | -trq | -trq_rpm | -mpg_c | -mpg_h | -drivetrain | -trsmn | -msrp | -
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
United States | -|||||||||||||
Ford | -GT | -2017 | -Base Coupe | -coupe | -647 | -6250 | -550 | -5900 | -11 | -18 | -rwd | -7a | -447000 | -
Dodge | -Viper | -2017 | -GT Coupe | -coupe | -645 | -5000 | -600 | -5000 | -12 | -19 | -rwd | -6m | -95895 | -
Italy | -|||||||||||||
Ferrari | -LaFerrari | -2015 | -Base Coupe | -coupe | -949 | -9000 | -664 | -6750 | -12 | -16 | -rwd | -7a | -1416362 | -
Lamborghini | -Aventador | -2015 | -LP 700-4 Coupe | -coupe | -700 | -8250 | -507 | -5500 | -11 | -18 | -awd | -7a | -397500 | -
Japan | -|||||||||||||
Acura | -NSX | -2017 | -Base Coupe | -coupe | -573 | -6500 | -476 | -2000 | -21 | -22 | -awd | -9a | -156000 | -
Nissan | -GT-R | -2016 | -Premium Coupe | -coupe | -545 | -6400 | -436 | -3200 | -16 | -22 | -awd | -6a | -101770 | -
Germany | -|||||||||||||
BMW | -i8 | -2016 | -Mega World Coupe | -coupe | -357 | -5800 | -420 | -3700 | -28 | -29 | -awd | -6am | -140700 | -
Mercedes-Benz | -AMG GT | -2016 | -S Coupe | -coupe | -503 | -6250 | -479 | -1750 | -16 | -22 | -rwd | -7a | -129900 | -
Getting the row groups in the preferred order can be done easily with dplyrās arrange()
function. For example, we can have groups that are arranged alphabetically by manufacturer (mfr
) and then sorted by highest sticker price (msrp
) to lowest.
mfr | -model | -year | -trim | -bdy_style | -hp | -hp_rpm | -trq | -trq_rpm | -mpg_c | -mpg_h | -drivetrain | -trsmn | -msrp | -
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Japan | -|||||||||||||
Acura | -NSX | -2017 | -Base Coupe | -coupe | -573 | -6500 | -476 | -2000 | -21 | -22 | -awd | -9a | -156000 | -
Nissan | -GT-R | -2016 | -Premium Coupe | -coupe | -545 | -6400 | -436 | -3200 | -16 | -22 | -awd | -6a | -101770 | -
Germany | -|||||||||||||
BMW | -i8 | -2016 | -Mega World Coupe | -coupe | -357 | -5800 | -420 | -3700 | -28 | -29 | -awd | -6am | -140700 | -
Mercedes-Benz | -AMG GT | -2016 | -S Coupe | -coupe | -503 | -6250 | -479 | -1750 | -16 | -22 | -rwd | -7a | -129900 | -
United States | -|||||||||||||
Dodge | -Viper | -2017 | -GT Coupe | -coupe | -645 | -5000 | -600 | -5000 | -12 | -19 | -rwd | -6m | -95895 | -
Ford | -GT | -2017 | -Base Coupe | -coupe | -647 | -6250 | -550 | -5900 | -11 | -18 | -rwd | -7a | -447000 | -
Italy | -|||||||||||||
Ferrari | -LaFerrari | -2015 | -Base Coupe | -coupe | -949 | -9000 | -664 | -6750 | -12 | -16 | -rwd | -7a | -1416362 | -
Lamborghini | -Aventador | -2015 | -LP 700-4 Coupe | -coupe | -700 | -8250 | -507 | -5500 | -11 | -18 | -awd | -7a | -397500 | -
We could also use factor levels to get a more particular ordering within arrange()
. For example, we can first arrange the groups themselves (the country of origināctry_origin
) by our own preferred ordering and then arrange by mfr
and descending msrp
as before. Then, group_by(ctry_origin)
can be used on the sorted tibble before passing this to gt()
.
# Define our preferred order `ctry_origin`
-order_countries <- c("Germany", "Italy", "United States", "Japan")
-
-# Reorder the table rows by our specific ordering of groups
-gtcars_8 %>%
- dplyr::arrange(
- factor(ctry_origin, levels = order_countries), mfr, desc(msrp)
- ) %>%
- dplyr::group_by(ctry_origin) %>%
- gt()
mfr | -model | -year | -trim | -bdy_style | -hp | -hp_rpm | -trq | -trq_rpm | -mpg_c | -mpg_h | -drivetrain | -trsmn | -msrp | -
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Germany | -|||||||||||||
BMW | -i8 | -2016 | -Mega World Coupe | -coupe | -357 | -5800 | -420 | -3700 | -28 | -29 | -awd | -6am | -140700 | -
Mercedes-Benz | -AMG GT | -2016 | -S Coupe | -coupe | -503 | -6250 | -479 | -1750 | -16 | -22 | -rwd | -7a | -129900 | -
Italy | -|||||||||||||
Ferrari | -LaFerrari | -2015 | -Base Coupe | -coupe | -949 | -9000 | -664 | -6750 | -12 | -16 | -rwd | -7a | -1416362 | -
Lamborghini | -Aventador | -2015 | -LP 700-4 Coupe | -coupe | -700 | -8250 | -507 | -5500 | -11 | -18 | -awd | -7a | -397500 | -
United States | -|||||||||||||
Dodge | -Viper | -2017 | -GT Coupe | -coupe | -645 | -5000 | -600 | -5000 | -12 | -19 | -rwd | -6m | -95895 | -
Ford | -GT | -2017 | -Base Coupe | -coupe | -647 | -6250 | -550 | -5900 | -11 | -18 | -rwd | -7a | -447000 | -
Japan | -|||||||||||||
Acura | -NSX | -2017 | -Base Coupe | -coupe | -573 | -6500 | -476 | -2000 | -21 | -22 | -awd | -9a | -156000 | -
Nissan | -GT-R | -2016 | -Premium Coupe | -coupe | -545 | -6400 | -436 | -3200 | -16 | -22 | -awd | -6a | -101770 | -
The last variation is to combine the manufacturer name with the model name, using those combined strings as row labels for the table. This is just a little more dplyr where we can use dplyr::mutate()
to make a new car
column followed by dplyr::select()
where we remove the mfr
and model
columns. When introducing the tibble to the gt()
function, we can now use the rowname_col
argument to specify a column that will serve as row labels (which is the newly made car
column).
# Reorder the table rows by our specific ordering of groups
-tab <-
- gtcars_8 %>%
- dplyr::arrange(
- factor(ctry_origin, levels = order_countries),
- mfr, desc(msrp)
- ) %>%
- dplyr::mutate(car = paste(mfr, model)) %>%
- dplyr::select(-mfr, -model) %>%
- dplyr::group_by(ctry_origin) %>%
- gt(rowname_col = "car")
-
-# Show the table
-tab
- | year | -trim | -bdy_style | -hp | -hp_rpm | -trq | -trq_rpm | -mpg_c | -mpg_h | -drivetrain | -trsmn | -msrp | -
---|---|---|---|---|---|---|---|---|---|---|---|---|
Germany | -||||||||||||
BMW i8 | -2016 | -Mega World Coupe | -coupe | -357 | -5800 | -420 | -3700 | -28 | -29 | -awd | -6am | -140700 | -
Mercedes-Benz AMG GT | -2016 | -S Coupe | -coupe | -503 | -6250 | -479 | -1750 | -16 | -22 | -rwd | -7a | -129900 | -
Italy | -||||||||||||
Ferrari LaFerrari | -2015 | -Base Coupe | -coupe | -949 | -9000 | -664 | -6750 | -12 | -16 | -rwd | -7a | -1416362 | -
Lamborghini Aventador | -2015 | -LP 700-4 Coupe | -coupe | -700 | -8250 | -507 | -5500 | -11 | -18 | -awd | -7a | -397500 | -
United States | -||||||||||||
Dodge Viper | -2017 | -GT Coupe | -coupe | -645 | -5000 | -600 | -5000 | -12 | -19 | -rwd | -6m | -95895 | -
Ford GT | -2017 | -Base Coupe | -coupe | -647 | -6250 | -550 | -5900 | -11 | -18 | -rwd | -7a | -447000 | -
Japan | -||||||||||||
Acura NSX | -2017 | -Base Coupe | -coupe | -573 | -6500 | -476 | -2000 | -21 | -22 | -awd | -9a | -156000 | -
Nissan GT-R | -2016 | -Premium Coupe | -coupe | -545 | -6400 | -436 | -3200 | -16 | -22 | -awd | -6a | -101770 | -
Letās hide two columns that we donāt need to the final table: drivetrain
and bdy_style
. We can use the cols_hide()
function to hide columns. The same end result might also have been achieved by using gtcars %>% dplyr::select(-c(drivetrain, bdy_style))
, before introducing the table to gt()
. Why this function then? Sometimes youāll need variables for conditional statements within gt but wonāt want to display them in the end.
Aside from hiding columns, letās move some of them. Again, this could be done with dplyr::select()
but there are options here in gt via the cols_move_to_start()
, cols_move()
, and cols_move_to_end()
functions.
# Use a few `cols_*()` functions to hide and move columns
-tab <-
- tab %>%
- cols_hide(columns = vars(drivetrain, bdy_style)) %>%
- cols_move(
- columns = vars(trsmn, mpg_c, mpg_h),
- after = vars(trim)
- )
-
-# Show the table
-tab
- | year | -trim | -trsmn | -mpg_c | -mpg_h | -hp | -hp_rpm | -trq | -trq_rpm | -msrp | -
---|---|---|---|---|---|---|---|---|---|---|
Germany | -||||||||||
BMW i8 | -2016 | -Mega World Coupe | -6am | -28 | -29 | -357 | -5800 | -420 | -3700 | -140700 | -
Mercedes-Benz AMG GT | -2016 | -S Coupe | -7a | -16 | -22 | -503 | -6250 | -479 | -1750 | -129900 | -
Italy | -||||||||||
Ferrari LaFerrari | -2015 | -Base Coupe | -7a | -12 | -16 | -949 | -9000 | -664 | -6750 | -1416362 | -
Lamborghini Aventador | -2015 | -LP 700-4 Coupe | -7a | -11 | -18 | -700 | -8250 | -507 | -5500 | -397500 | -
United States | -||||||||||
Dodge Viper | -2017 | -GT Coupe | -6m | -12 | -19 | -645 | -5000 | -600 | -5000 | -95895 | -
Ford GT | -2017 | -Base Coupe | -7a | -11 | -18 | -647 | -6250 | -550 | -5900 | -447000 | -
Japan | -||||||||||
Acura NSX | -2017 | -Base Coupe | -9a | -21 | -22 | -573 | -6500 | -476 | -2000 | -156000 | -
Nissan GT-R | -2016 | -Premium Coupe | -6a | -16 | -22 | -545 | -6400 | -436 | -3200 | -101770 | -
Itās sometimes useful to arrange variables/columns into groups by using spanner column labels. This can be done in gt by using the tab_spanner()
function. It takes the label
and columns
arguments; label
is the spanner column label and the columns
are those columns that belong in this group.
Here, weāll put the mpg_c
, mpg_h
, hp
, hp_rpm
, trq
, trq_rpm
columns under the Performance
spanner column, and the remaining columns wonāt be grouped together. This single spanner column label is styled with Markdown by using the md()
helper.
# Put the first three columns under a spanner
-# column with the label 'Performance'
-tab <-
- tab %>%
- tab_spanner(
- label = md("*Performance*"),
- columns = vars(mpg_c, mpg_h, hp, hp_rpm, trq, trq_rpm)
- )
-
-# Show the table
-tab
- | year | -trim | -trsmn | -Performance | -msrp | -|||||
---|---|---|---|---|---|---|---|---|---|---|
mpg_c | -mpg_h | -hp | -hp_rpm | -trq | -trq_rpm | -|||||
Germany | -||||||||||
BMW i8 | -2016 | -Mega World Coupe | -6am | -28 | -29 | -357 | -5800 | -420 | -3700 | -140700 | -
Mercedes-Benz AMG GT | -2016 | -S Coupe | -7a | -16 | -22 | -503 | -6250 | -479 | -1750 | -129900 | -
Italy | -||||||||||
Ferrari LaFerrari | -2015 | -Base Coupe | -7a | -12 | -16 | -949 | -9000 | -664 | -6750 | -1416362 | -
Lamborghini Aventador | -2015 | -LP 700-4 Coupe | -7a | -11 | -18 | -700 | -8250 | -507 | -5500 | -397500 | -
United States | -||||||||||
Dodge Viper | -2017 | -GT Coupe | -6m | -12 | -19 | -645 | -5000 | -600 | -5000 | -95895 | -
Ford GT | -2017 | -Base Coupe | -7a | -11 | -18 | -647 | -6250 | -550 | -5900 | -447000 | -
Japan | -||||||||||
Acura NSX | -2017 | -Base Coupe | -9a | -21 | -22 | -573 | -6500 | -476 | -2000 | -156000 | -
Nissan GT-R | -2016 | -Premium Coupe | -6a | -16 | -22 | -545 | -6400 | -436 | -3200 | -101770 | -
Sometimes weād like to combine the data from two columns into a single column. The cols_merge()
function allows us to do this, we just need to describe how the data should be combined. For our table, letās merge together the following pairs of columns:
mpg_c
and mpg_h
(miles per gallon in city and highway driving modes)hp
and hp_rpm
(horsepower and associated RPM)trq
and trq_rpm
(torque and associated RPM)The cols_merge()
function uses a col_1
column and a col_2
column. Once combined, the col_1
column will be retained and the col_2
column will be dropped. The pattern argument uses {1}
and {2}
to represent the content of col_1
and col_2
. Here, we can use string literals to add text like rpm
or the @
sign. Furthermore, because we are targeting an HTML table, we can use the <br>
tag to insert a linebreak.
Labeling columns essentially means that we are choosing display-friendly labels that are no longer simply the column names (the default label). The cols_label()
function makes this relabeling possible. It accepts a series of named arguments in the form of <column_name> = <column_label>, ...
.
# Perform three column merges to better present
-# MPG, HP, and torque; relabel all the remaining
-# columns for a nicer-looking presentation
-tab <-
- tab %>%
- cols_merge(
- col_1 = vars(mpg_c),
- col_2 = vars(mpg_h),
- pattern = "{1}c<br>{2}h"
- ) %>%
- cols_merge(
- col_1 = vars(hp),
- col_2 = vars(hp_rpm),
- pattern = "{1}<br>@{2}rpm"
- ) %>%
- cols_merge(
- col_1 = vars(trq),
- col_2 = vars(trq_rpm),
- pattern = "{1}<br>@{2}rpm"
- ) %>%
- cols_label(
- mpg_c = "MPG",
- hp = "HP",
- trq = "Torque",
- year = "Year",
- trim = "Trim",
- trsmn = "Transmission",
- msrp = "MSRP"
- )
-
-# Show the table
-tab
- | Year | -Trim | -Transmission | -Performance | -MSRP | -||
---|---|---|---|---|---|---|---|
MPG | -HP | -Torque | -|||||
Germany | -|||||||
BMW i8 | -2016 | -Mega World Coupe | -6am | -28c 29h |
-357 @5800rpm |
-420 @3700rpm |
-140700 | -
Mercedes-Benz AMG GT | -2016 | -S Coupe | -7a | -16c 22h |
-503 @6250rpm |
-479 @1750rpm |
-129900 | -
Italy | -|||||||
Ferrari LaFerrari | -2015 | -Base Coupe | -7a | -12c 16h |
-949 @9000rpm |
-664 @6750rpm |
-1416362 | -
Lamborghini Aventador | -2015 | -LP 700-4 Coupe | -7a | -11c 18h |
-700 @8250rpm |
-507 @5500rpm |
-397500 | -
United States | -|||||||
Dodge Viper | -2017 | -GT Coupe | -6m | -12c 19h |
-645 @5000rpm |
-600 @5000rpm |
-95895 | -
Ford GT | -2017 | -Base Coupe | -7a | -11c 18h |
-647 @6250rpm |
-550 @5900rpm |
-447000 | -
Japan | -|||||||
Acura NSX | -2017 | -Base Coupe | -9a | -21c 22h |
-573 @6500rpm |
-476 @2000rpm |
-156000 | -
Nissan GT-R | -2016 | -Premium Coupe | -6a | -16c 22h |
-545 @6400rpm |
-436 @3200rpm |
-101770 | -
There are a number of formatter functions, all with the general naming convention fmt*()
. The various formatters are convenient for applying formats to numeric or character values in the tableās field. Here, we will simply use fmt_currency()
on the msrp
column (we still refer to columns by their original names) to get USD currency will no decimal places. Weāre not supplying anything for the rows
argument and this means we want to apply the formatting to the entire column of data.
# Format the `msrp` column to USD currency
-# with no display of the currency subunits
-tab <-
- tab %>%
- fmt_currency(
- columns = vars(msrp),
- currency = "USD",
- decimals = 0
- )
-
-# Show the table
-tab
- | Year | -Trim | -Transmission | -Performance | -MSRP | -||
---|---|---|---|---|---|---|---|
MPG | -HP | -Torque | -|||||
Germany | -|||||||
BMW i8 | -2016 | -Mega World Coupe | -6am | -28c 29h |
-357 @5800rpm |
-420 @3700rpm |
-$140,700 | -
Mercedes-Benz AMG GT | -2016 | -S Coupe | -7a | -16c 22h |
-503 @6250rpm |
-479 @1750rpm |
-$129,900 | -
Italy | -|||||||
Ferrari LaFerrari | -2015 | -Base Coupe | -7a | -12c 16h |
-949 @9000rpm |
-664 @6750rpm |
-$1,416,362 | -
Lamborghini Aventador | -2015 | -LP 700-4 Coupe | -7a | -11c 18h |
-700 @8250rpm |
-507 @5500rpm |
-$397,500 | -
United States | -|||||||
Dodge Viper | -2017 | -GT Coupe | -6m | -12c 19h |
-645 @5000rpm |
-600 @5000rpm |
-$95,895 | -
Ford GT | -2017 | -Base Coupe | -7a | -11c 18h |
-647 @6250rpm |
-550 @5900rpm |
-$447,000 | -
Japan | -|||||||
Acura NSX | -2017 | -Base Coupe | -9a | -21c 22h |
-573 @6500rpm |
-476 @2000rpm |
-$156,000 | -
Nissan GT-R | -2016 | -Premium Coupe | -6a | -16c 22h |
-545 @6400rpm |
-436 @3200rpm |
-$101,770 | -
We can change the alignment of data in columns with cols_align()
. For our table, letās center-align the mpg_c
, hp
, and trq
columns. All other columns will maintain their default alignments.
Itās sometimes useful to modify the default styles of table cells. We can do this in a targeted way with the tab_style()
function. That function require two key pieces of information: a style
definition, and one or more locations
(which cells should the styles be applied to?). The style
argument commonly uses the cells_styles()
helper function, which contains arguments for all the styles that are supported (use ?cells_styles
for more information on this). Here we will use a text size of 12px
in our targeted cellsāboth px(12)
and "12px"
work equally well here. We also use helper functions with the locations
argument and these are the cells_*()
functions. We would like to target the data cells in all columns except year
and msrp
so we need to use cells_data
and then supply our target columns to the columns
argument.
# Center-align three columns in the gt table
-# and modify the text size of a few columns
-# of data
-tab <-
- tab %>%
- cols_align(
- align = "center",
- columns = vars(mpg_c, hp, trq)
- ) %>%
- tab_style(
- style = cells_styles(
- text_size = px(12)),
- locations = cells_data(
- columns = vars(trim, trsmn, mpg_c, hp, trq))
- )
-
-# Show the table
-tab
- | Year | -Trim | -Transmission | -Performance | -MSRP | -||
---|---|---|---|---|---|---|---|
MPG | -HP | -Torque | -|||||
Germany | -|||||||
BMW i8 | -2016 | -Mega World Coupe | -6am | -28c 29h |
-357 @5800rpm |
-420 @3700rpm |
-$140,700 | -
Mercedes-Benz AMG GT | -2016 | -S Coupe | -7a | -16c 22h |
-503 @6250rpm |
-479 @1750rpm |
-$129,900 | -
Italy | -|||||||
Ferrari LaFerrari | -2015 | -Base Coupe | -7a | -12c 16h |
-949 @9000rpm |
-664 @6750rpm |
-$1,416,362 | -
Lamborghini Aventador | -2015 | -LP 700-4 Coupe | -7a | -11c 18h |
-700 @8250rpm |
-507 @5500rpm |
-$397,500 | -
United States | -|||||||
Dodge Viper | -2017 | -GT Coupe | -6m | -12c 19h |
-645 @5000rpm |
-600 @5000rpm |
-$95,895 | -
Ford GT | -2017 | -Base Coupe | -7a | -11c 18h |
-647 @6250rpm |
-550 @5900rpm |
-$447,000 | -
Japan | -|||||||
Acura NSX | -2017 | -Base Coupe | -9a | -21c 22h |
-573 @6500rpm |
-476 @2000rpm |
-$156,000 | -
Nissan GT-R | -2016 | -Premium Coupe | -6a | -16c 22h |
-545 @6400rpm |
-436 @3200rpm |
-$101,770 | -
A text transform via the text_transform()
function is a great way to further manipulate text in data cells (even after theyāve been formatted with the fmt*()
function). After targeting data cells with the cells_data()
location helper function, we supply a function to the fn
argument that processes a vector of text. If we intend to render as an HTML table, we can directly apply HTML tags in the transformation function. The function we provide here will build strings that read better in a display table.
# Transform the column of text in `trsmn` using
-# a custom function within `text_transform()`;
-# here `x` represents a character vector defined
-# in the `cells_data()` function
-tab <-
- tab %>%
- text_transform(
- locations = cells_data(columns = vars(trsmn)),
- fn = function(x) {
-
- # The first character of `x` always
- # indicates the number of transmission speeds
- speed <- substr(x, 1, 1)
-
- # We can carefully determine which transmission
- # type we have in `x` with a `dplyr::case_when()`
- # statement
- type <-
- dplyr::case_when(
- substr(x, 2, 3) == "am" ~ "Automatic/Manual",
- substr(x, 2, 2) == "m" ~ "Manual",
- substr(x, 2, 2) == "a" ~ "Automatic",
- substr(x, 2, 3) == "dd" ~ "Direct Drive"
- )
-
- # Let's paste together the `speed` and `type`
- # vectors to create HTML text replacing `x`
- paste(speed, " Speed<br><em>", type, "</em>")
- }
- )
-
-# Show the table
-tab
- | Year | -Trim | -Transmission | -Performance | -MSRP | -||
---|---|---|---|---|---|---|---|
MPG | -HP | -Torque | -|||||
Germany | -|||||||
BMW i8 | -2016 | -Mega World Coupe | -6 Speed Automatic/Manual - |
-28c 29h |
-357 @5800rpm |
-420 @3700rpm |
-$140,700 | -
Mercedes-Benz AMG GT | -2016 | -S Coupe | -7 Speed Automatic - |
-16c 22h |
-503 @6250rpm |
-479 @1750rpm |
-$129,900 | -
Italy | -|||||||
Ferrari LaFerrari | -2015 | -Base Coupe | -7 Speed Automatic - |
-12c 16h |
-949 @9000rpm |
-664 @6750rpm |
-$1,416,362 | -
Lamborghini Aventador | -2015 | -LP 700-4 Coupe | -7 Speed Automatic - |
-11c 18h |
-700 @8250rpm |
-507 @5500rpm |
-$397,500 | -
United States | -|||||||
Dodge Viper | -2017 | -GT Coupe | -6 Speed Manual - |
-12c 19h |
-645 @5000rpm |
-600 @5000rpm |
-$95,895 | -
Ford GT | -2017 | -Base Coupe | -7 Speed Automatic - |
-11c 18h |
-647 @6250rpm |
-550 @5900rpm |
-$447,000 | -
Japan | -|||||||
Acura NSX | -2017 | -Base Coupe | -9 Speed Automatic - |
-21c 22h |
-573 @6500rpm |
-476 @2000rpm |
-$156,000 | -
Nissan GT-R | -2016 | -Premium Coupe | -6 Speed Automatic - |
-16c 22h |
-545 @6400rpm |
-436 @3200rpm |
-$101,770 | -
The tab_header()
function allows us to place a table title and, optionally, a subtitle at the top of the display table. Itās generally a good idea to have both in a table, where the subtitle provides additional information (though that isnāt quite the case in our example below).
# Add a table title and subtitle; we can use
-# markdown with the `md()` helper function
-tab <-
- tab %>%
- tab_header(
- title = md("The Cars of **gtcars**"),
- subtitle = "These are some fine automobiles"
- )
-
-# Show the table
-tab
The Cars of gtcars - | -|||||||
---|---|---|---|---|---|---|---|
These are some fine automobiles | -|||||||
- | Year | -Trim | -Transmission | -Performance | -MSRP | -||
MPG | -HP | -Torque | -|||||
Germany | -|||||||
BMW i8 | -2016 | -Mega World Coupe | -6 Speed Automatic/Manual - |
-28c 29h |
-357 @5800rpm |
-420 @3700rpm |
-$140,700 | -
Mercedes-Benz AMG GT | -2016 | -S Coupe | -7 Speed Automatic - |
-16c 22h |
-503 @6250rpm |
-479 @1750rpm |
-$129,900 | -
Italy | -|||||||
Ferrari LaFerrari | -2015 | -Base Coupe | -7 Speed Automatic - |
-12c 16h |
-949 @9000rpm |
-664 @6750rpm |
-$1,416,362 | -
Lamborghini Aventador | -2015 | -LP 700-4 Coupe | -7 Speed Automatic - |
-11c 18h |
-700 @8250rpm |
-507 @5500rpm |
-$397,500 | -
United States | -|||||||
Dodge Viper | -2017 | -GT Coupe | -6 Speed Manual - |
-12c 19h |
-645 @5000rpm |
-600 @5000rpm |
-$95,895 | -
Ford GT | -2017 | -Base Coupe | -7 Speed Automatic - |
-11c 18h |
-647 @6250rpm |
-550 @5900rpm |
-$447,000 | -
Japan | -|||||||
Acura NSX | -2017 | -Base Coupe | -9 Speed Automatic - |
-21c 22h |
-573 @6500rpm |
-476 @2000rpm |
-$156,000 | -
Nissan GT-R | -2016 | -Premium Coupe | -6 Speed Automatic - |
-16c 22h |
-545 @6400rpm |
-436 @3200rpm |
-$101,770 | -
A source note can be added below the display table using the tab_source_note()
function. We can even add multiple source notes with multiple calls of that function. Here, we supply a web URL and by using Markdown (with md()
) itās easy to create a link to the source of the data.
# Add a source note to the bottom of the table; this
-# appears below the footnotes
-tab <-
- tab %>%
- tab_source_note(
- source_note = md(
- "Source: Various pages within [edmunds.com](https://www.edmunds.com).")
- )
-
-# Show the table
-tab
The Cars of gtcars - | -||||||||
---|---|---|---|---|---|---|---|---|
These are some fine automobiles | -||||||||
- | Year | -Trim | -Transmission | -Performance | -MSRP | -|||
MPG | -HP | -Torque | -||||||
Germany | -||||||||
BMW i8 | -2016 | -Mega World Coupe | -6 Speed Automatic/Manual - |
-28c 29h |
-357 @5800rpm |
-420 @3700rpm |
-$140,700 | -|
Mercedes-Benz AMG GT | -2016 | -S Coupe | -7 Speed Automatic - |
-16c 22h |
-503 @6250rpm |
-479 @1750rpm |
-$129,900 | -|
Italy | -||||||||
Ferrari LaFerrari | -2015 | -Base Coupe | -7 Speed Automatic - |
-12c 16h |
-949 @9000rpm |
-664 @6750rpm |
-$1,416,362 | -|
Lamborghini Aventador | -2015 | -LP 700-4 Coupe | -7 Speed Automatic - |
-11c 18h |
-700 @8250rpm |
-507 @5500rpm |
-$397,500 | -|
United States | -||||||||
Dodge Viper | -2017 | -GT Coupe | -6 Speed Manual - |
-12c 19h |
-645 @5000rpm |
-600 @5000rpm |
-$95,895 | -|
Ford GT | -2017 | -Base Coupe | -7 Speed Automatic - |
-11c 18h |
-647 @6250rpm |
-550 @5900rpm |
-$447,000 | -|
Japan | -||||||||
Acura NSX | -2017 | -Base Coupe | -9 Speed Automatic - |
-21c 22h |
-573 @6500rpm |
-476 @2000rpm |
-$156,000 | -|
Nissan GT-R | -2016 | -Premium Coupe | -6 Speed Automatic - |
-16c 22h |
-545 @6400rpm |
-436 @3200rpm |
-$101,770 | -|
Source: Various pages within edmunds.com. | -
gtcars
table and Adding FootnotesLetās bring it all together by putting together all the statements we developed for gtcars_8
, and applying that to the complete gtcars
dataset. At the same time, weāll add a few interesting footnotes and our specific requirements for footnoting are:
a. identifying the car with the best gas mileage (city)
-b. identifying the car with the highest horsepower
-c. stating the currency of the MSRP
-The tab_footnote()
function expects note text for the footnote
argument, and locations for where the glyph should be attached. It will handle the placement of the note glyph and also place the footnote in the footnotes area. Here, weāll use the cells_data()
location helper function. There are several location helper functions for targeting all parts of the table (e.g,. cells_data()
, cells_stub()
, etc.). Each location helper has their own interface for targeting cells, help is available at ?gt::location_cells
.
What cells_data()
expects is columns
(column names, which can be conveniently provided in vars()
) and rows
(which can be a vector of row names or row indices). The cells_stub()
location helper only expects a vector of rows
. For cells_column_labels()
, we can either provided targeted column labels in the columns
argument or spanner column labels in the groups
argument. Here, we are targeting a footnote to the msrp
column label so we will use columns = vars(msrp)
.
In terms of structuring the code, weāre taking all the previous statements and putting those in first. It should be noted that the order of the statements does not matter to the end result, we could also put in all of the tab_footnote()
statements first (again, any in order) and expect the same output table.
-# Use dplyr functions to get the car with the best city gas mileage;
-# this will be used to target the correct cell for a footnote
-best_gas_mileage_city <-
- gtcars %>%
- dplyr::arrange(desc(mpg_c)) %>%
- dplyr::slice(1) %>%
- dplyr::mutate(car = paste(mfr, model)) %>%
- dplyr::pull(car)
-
-# Use dplyr functions to get the car with the highest horsepower
-# this will be used to target the correct cell for a footnote
-highest_horsepower <-
- gtcars %>%
- dplyr::arrange(desc(hp)) %>%
- dplyr::slice(1) %>%
- dplyr::mutate(car = paste(mfr, model)) %>%
- dplyr::pull(car)
-
-# Create a display table with `gtcars`, using all of the previous
-# statements piped together + additional `tab_footnote()` stmts
-tab <-
- gtcars %>%
- dplyr::arrange(
- factor(ctry_origin, levels = order_countries),
- mfr, desc(msrp)
- ) %>%
- dplyr::mutate(car = paste(mfr, model)) %>%
- dplyr::select(-mfr, -model) %>%
- dplyr::group_by(ctry_origin) %>%
- gt(rowname_col = "car") %>%
- cols_hide(columns = vars(drivetrain, bdy_style)) %>%
- cols_move(
- columns = vars(trsmn, mpg_c, mpg_h),
- after = vars(trim)
- ) %>%
- tab_spanner(
- label = md("*Performance*"),
- columns = vars(mpg_c, mpg_h, hp, hp_rpm, trq, trq_rpm)
- ) %>%
- cols_merge(
- col_1 = vars(mpg_c),
- col_2 = vars(mpg_h),
- pattern = "{1}c<br>{2}h"
- ) %>%
- cols_merge(
- col_1 = vars(hp),
- col_2 = vars(hp_rpm),
- pattern = "{1}<br>@{2}rpm"
- ) %>%
- cols_merge(
- col_1 = vars(trq),
- col_2 = vars(trq_rpm),
- pattern = "{1}<br>@{2}rpm"
- ) %>%
- cols_label(
- mpg_c = "MPG",
- hp = "HP",
- trq = "Torque",
- year = "Year",
- trim = "Trim",
- trsmn = "Transmission",
- msrp = "MSRP"
- ) %>%
- fmt_currency(
- columns = vars(msrp),
- currency = "USD",
- decimals = 0
- ) %>%
- cols_align(
- align = "center",
- columns = vars(mpg_c, hp, trq)
- ) %>%
- tab_style(
- style = cells_styles(text_size = px(12)),
- locations = cells_data(columns = vars(trim, trsmn, mpg_c, hp, trq))
- ) %>%
- text_transform(
- locations = cells_data(columns = vars(trsmn)),
- fn = function(x) {
-
- speed <- substr(x, 1, 1)
-
- type <-
- dplyr::case_when(
- substr(x, 2, 3) == "am" ~ "Automatic/Manual",
- substr(x, 2, 2) == "m" ~ "Manual",
- substr(x, 2, 2) == "a" ~ "Automatic",
- substr(x, 2, 3) == "dd" ~ "Direct Drive"
- )
-
- paste(speed, " Speed<br><em>", type, "</em>")
- }
- ) %>%
- tab_header(
- title = md("The Cars of **gtcars**"),
- subtitle = "These are some fine automobiles"
- ) %>%
- tab_source_note(
- source_note = md(
- "Source: Various pages within [edmunds.com](https://www.edmunds.com).")
- ) %>%
- tab_footnote(
- footnote = md("Best gas mileage (city) of all the **gtcars**."),
- locations = cells_data(
- columns = vars(mpg_c),
- rows = best_gas_mileage_city)
- ) %>%
- tab_footnote(
- footnote = md("The highest horsepower of all the **gtcars**."),
- locations = cells_data(
- columns = vars(hp),
- rows = highest_horsepower)
- ) %>%
- tab_footnote(
- footnote = "All prices in U.S. dollars (USD).",
- locations = cells_column_labels(
- columns = vars(msrp))
- )
-
-# Show the table
-tab
The Cars of gtcars - | -||||||||
---|---|---|---|---|---|---|---|---|
These are some fine automobiles | -||||||||
- | Year | -Trim | -Transmission | -Performance | -MSRP1 - | -|||
MPG | -HP | -Torque | -||||||
Germany | -||||||||
Audi R8 | -2015 | -4.2 (Manual) Coupe | -6 Speed Manual - |
-11c 20h |
-430 @7900rpm |
-317 @4500rpm |
-$115,900 | -|
Audi S8 | -2016 | -Base Sedan | -8 Speed Automatic/Manual - |
-15c 25h |
-520 @5800rpm |
-481 @1700rpm |
-$114,900 | -|
Audi RS 7 | -2016 | -Quattro Hatchback | -8 Speed Automatic/Manual - |
-15c 25h |
-560 @5700rpm |
-516 @1750rpm |
-$108,900 | -|
Audi S7 | -2016 | -Prestige quattro Hatchback | -7 Speed Automatic - |
-17c 27h |
-450 @5800rpm |
-406 @1400rpm |
-$82,900 | -|
Audi S6 | -2016 | -Premium Plus quattro Sedan | -7 Speed Automatic - |
-18c 27h |
-450 @5800rpm |
-406 @1400rpm |
-$70,900 | -|
BMW i8 | -2016 | -Mega World Coupe | -6 Speed Automatic/Manual - |
-28c 29h2 - |
-357 @5800rpm |
-420 @3700rpm |
-$140,700 | -|
BMW M6 | -2016 | -Base Coupe | -7 Speed Automatic - |
-15c 22h |
-560 @6000rpm |
-500 @1500rpm |
-$113,400 | -|
BMW M5 | -2016 | -Base Sedan | -7 Speed Automatic/Manual - |
-15c 22h |
-560 @6000rpm |
-500 @1500rpm |
-$94,100 | -|
BMW 6-Series | -2016 | -640 I Coupe | -8 Speed Automatic/Manual - |
-20c 30h |
-315 @5800rpm |
-330 @1400rpm |
-$77,300 | -|
BMW M4 | -2016 | -Base Coupe | -6 Speed Manual - |
-17c 24h |
-425 @5500rpm |
-406 @1850rpm |
-$65,700 | -|
Mercedes-Benz AMG GT | -2016 | -S Coupe | -7 Speed Automatic - |
-16c 22h |
-503 @6250rpm |
-479 @1750rpm |
-$129,900 | -|
Mercedes-Benz SL-Class | -2016 | -SL400 Convertible | -7 Speed Automatic/Manual - |
-20c 27h |
-329 @5250rpm |
-354 @1600rpm |
-$85,050 | -|
Porsche 911 | -2016 | -Carrera Coupe | -7 Speed Manual - |
-20c 28h |
-350 @7400rpm |
-287 @5600rpm |
-$84,300 | -|
Porsche Panamera | -2016 | -Base Sedan | -7 Speed Automatic - |
-18c 28h |
-310 @6200rpm |
-295 @3750rpm |
-$78,100 | -|
Porsche 718 Boxster | -2017 | -Base Convertible | -6 Speed Manual - |
-21c 28h |
-300 @6500rpm |
-280 @1950rpm |
-$56,000 | -|
Porsche 718 Cayman | -2017 | -Base Coupe | -6 Speed Manual - |
-20c 29h |
-300 @6500rpm |
-280 @1950rpm |
-$53,900 | -|
Italy | -||||||||
Ferrari LaFerrari | -2015 | -Base Coupe | -7 Speed Automatic - |
-12c 16h |
-949 @9000rpm3 - |
-664 @6750rpm |
-$1,416,362 | -|
Ferrari F12Berlinetta | -2015 | -Base Coupe | -7 Speed Automatic - |
-11c 16h |
-731 @8250rpm |
-509 @6000rpm |
-$319,995 | -|
Ferrari GTC4Lusso | -2017 | -Base Coupe | -7 Speed Automatic - |
-12c 17h |
-680 @8250rpm |
-514 @5750rpm |
-$298,000 | -|
Ferrari FF | -2015 | -Base Coupe | -7 Speed Automatic - |
-11c 16h |
-652 @8000rpm |
-504 @6000rpm |
-$295,000 | -|
Ferrari 458 Speciale | -2015 | -Base Coupe | -7 Speed Automatic - |
-13c 17h |
-597 @9000rpm |
-398 @6000rpm |
-$291,744 | -|
Ferrari 458 Spider | -2015 | -Base | -7 Speed Automatic - |
-13c 17h |
-562 @9000rpm |
-398 @6000rpm |
-$263,553 | -|
Ferrari 488 GTB | -2016 | -Base Coupe | -7 Speed Automatic - |
-15c 22h |
-661 @8000rpm |
-561 @3000rpm |
-$245,400 | -|
Ferrari 458 Italia | -2014 | -Base Coupe | -7 Speed Automatic - |
-13c 17h |
-562 @9000rpm |
-398 @6000rpm |
-$233,509 | -|
Ferrari California | -2015 | -Base Convertible | -7 Speed Automatic - |
-16c 23h |
-553 @7500rpm |
-557 @4750rpm |
-$198,973 | -|
Lamborghini Aventador | -2015 | -LP 700-4 Coupe | -7 Speed Automatic - |
-11c 18h |
-700 @8250rpm |
-507 @5500rpm |
-$397,500 | -|
Lamborghini Huracan | -2015 | -LP 610-4 Coupe | -7 Speed Automatic - |
-16c 20h |
-610 @8250rpm |
-413 @6500rpm |
-$237,250 | -|
Lamborghini Gallardo | -2014 | -LP 550-2 Coupe | -6 Speed Automatic - |
-12c 20h |
-550 @8000rpm |
-398 @6500rpm |
-$191,900 | -|
Maserati Granturismo | -2016 | -Sport Coupe | -6 Speed Automatic/Manual - |
-13c 21h |
-454 @7600rpm |
-384 @4750rpm |
-$132,825 | -|
Maserati Quattroporte | -2016 | -S Sedan | -8 Speed Automatic/Manual - |
-16c 23h |
-404 @5500rpm |
-406 @1500rpm |
-$99,900 | -|
Maserati Ghibli | -2016 | -Base Sedan | -8 Speed Automatic/Manual - |
-17c 24h |
-345 @5250rpm |
-369 @1750rpm |
-$70,600 | -|
United States | -||||||||
Chevrolet Corvette | -2016 | -Z06 Coupe | -7 Speed Manual - |
-15c 22h |
-650 @6400rpm |
-650 @3600rpm |
-$88,345 | -|
Dodge Viper | -2017 | -GT Coupe | -6 Speed Manual - |
-12c 19h |
-645 @5000rpm |
-600 @5000rpm |
-$95,895 | -|
Ford GT | -2017 | -Base Coupe | -7 Speed Automatic - |
-11c 18h |
-647 @6250rpm |
-550 @5900rpm |
-$447,000 | -|
Tesla Model S | -2017 | -75D | -1 Speed Direct Drive - |
-NA | -259 @6100rpm |
-243 | -$74,500 | -|
Japan | -||||||||
Acura NSX | -2017 | -Base Coupe | -9 Speed Automatic - |
-21c 22h |
-573 @6500rpm |
-476 @2000rpm |
-$156,000 | -|
Nissan GT-R | -2016 | -Premium Coupe | -6 Speed Automatic - |
-16c 22h |
-545 @6400rpm |
-436 @3200rpm |
-$101,770 | -|
United Kingdom | -||||||||
Aston Martin Vanquish | -2016 | -Base Coupe | -8 Speed Automatic/Manual - |
-13c 21h |
-568 @6650rpm |
-465 @5500rpm |
-$287,250 | -|
Aston Martin DB11 | -2017 | -Base Coupe | -8 Speed Automatic/Manual - |
-15c 21h |
-608 @6500rpm |
-516 @1500rpm |
-$211,195 | -|
Aston Martin Rapide S | -2016 | -Base Sedan | -8 Speed Automatic/Manual - |
-14c 21h |
-552 @6650rpm |
-465 @5500rpm |
-$205,300 | -|
Aston Martin Vantage | -2016 | -V8 GT (Manual) Coupe | -6 Speed Manual - |
-13c 19h |
-430 @7300rpm |
-361 @5000rpm |
-$103,300 | -|
Bentley Continental GT | -2016 | -V8 Coupe | -8 Speed Automatic/Manual - |
-15c 25h |
-500 @6000rpm |
-487 @1700rpm |
-$198,500 | -|
Jaguar F-Type | -2016 | -Base (Manual) Coupe | -6 Speed Manual - |
-16c 24h |
-340 @6500rpm |
-332 @3500rpm |
-$65,000 | -|
Lotus Evora | -2017 | -2+2 Coupe | -6 Speed Manual - |
-16c 24h |
-400 @7000rpm |
-302 @3500rpm |
-$91,900 | -|
McLaren 570 | -2016 | -Base Coupe | -7 Speed Automatic - |
-16c 23h |
-570 @7500rpm |
-443 @5000rpm |
-$184,900 | -|
Rolls-Royce Dawn | -2016 | -Base Convertible | -8 Speed Automatic - |
-12c 19h |
-563 @5250rpm |
-575 @1500rpm |
-$335,000 | -|
Rolls-Royce Wraith | -2016 | -Base Coupe | -8 Speed Automatic - |
-13c 21h |
-624 @5600rpm |
-590 @1500rpm |
-$304,350 | -|
Source: Various pages within edmunds.com. | -||||||||
-1 All prices in U.S. dollars (USD). 2 Best gas mileage (city) of all the gtcars. 3 The highest horsepower of all the gtcars. |
-
That is it. The final table looks pretty good and conveys the additional information we planned for. That table can be used in a lot of different places like R Markdown, Shiny, email messagesā¦ wherever HTML is accepted.
-vignettes/creating-display-tables.Rmd
- creating-display-tables.Rmd
The gt package is all about making it simple to produce nice-looking display tables. Display tables? Well yes, we are trying to distinguish between data tables (e.g., tibbles, data.frame
s, etc.) and those tables youād find in a web page, a journal article, or in a magazine. Such tables can likewise be called presentation tables, summary tables, or just tables really. Here are some examples, ripped straight from the web:
We can think of display tables as output only, where weād not want to use them as input ever again. Other features include annotations, table element styling, and text transformations that serve to communicate the subject matter more clearly.
-Letās use a less common dataset that is available in the R datasets package: islands
. Itās actually not a data frame but a named vector. Thatās okay though, we can use use dplyr and prepare a tibble from it:
# Take the `islands` dataset and use some
-# dplyr functionality to obtain the ten
-# biggest islands in the world
-islands_tbl <-
- dplyr::data_frame(
- name = names(islands),
- size = islands
- ) %>%
- dplyr::arrange(desc(size)) %>%
- dplyr::slice(1:10)
-
-# Display the table
-islands_tbl
-#> # A tibble: 10 x 2
-#> name size
-#> <chr> <dbl>
-#> 1 Asia 16988
-#> 2 Africa 11506
-#> 3 North America 9390
-#> 4 South America 6795
-#> 5 Antarctica 5500
-#> 6 Europe 3745
-#> 7 Australia 2968
-#> 8 Greenland 840
-#> 9 New Guinea 306
-#> 10 Borneo 280
Given that islands_tbl
is a tibble, we now have a suitable input for gt.
The main entry point into the gt API is the gt()
function. If we pass islands_tbl
to the function gt()
, weāll get a gt Table as output. As an aside, we could have easily used a data frame instead as valid Table Data for gt.
# Create a display table showing ten of
-# the largest islands in the world
-gt_tbl <- gt(data = islands_tbl)
-
-# Show the gt Table
-gt_tbl
name | -size | -
---|---|
Asia | -16988 | -
Africa | -11506 | -
North America | -9390 | -
South America | -6795 | -
Antarctica | -5500 | -
Europe | -3745 | -
Australia | -2968 | -
Greenland | -840 | -
New Guinea | -306 | -
Borneo | -280 | -
That doesnāt look too bad. Sure, itās basic but we really didnāt really ask for much. We did receive a proper table with column labels and the data. Also, that default striping is a nice touch. Oftentimes however, youāll want a bit more: a Table header, a Stub, and sometimes footnotes and source notes in the Table Footer part.
-The gt package makes it relatively easy to add parts so that the resulting gt Table better conveys the information you want to present. These table parts work well together and there the possible variations in arrangement can handle most tabular presentation needs. The previous gt Table demonstrated had only two parts, the Column Labels and the Table Body. The next few examples will show all of the other table parts that are available.
-This is the way the main parts of a table (and their subparts) fit together:
-
-
The parts (roughly from top to bottom) are:
-The way that we add parts like the Table Header and footnotes in the Table Footer is to use the tab_*()
family of functions. A Table Header is easy to add so letās see how the previous table looks with a title and a subtitle. We can add this part using the tab_header()
function:
# Make a display table with the `islands_tbl`
-# table; put a heading just above the column labels
-gt_tbl <-
- gt_tbl %>%
- tab_header(
- title = "Large Landmasses of the World",
- subtitle = "The top ten largest are presented"
- )
-
-# Show the gt Table
-gt_tbl
Large Landmasses of the World | -|
---|---|
The top ten largest are presented | -|
name | -size | -
Asia | -16988 | -
Africa | -11506 | -
North America | -9390 | -
South America | -6795 | -
Antarctica | -5500 | -
Europe | -3745 | -
Australia | -2968 | -
Greenland | -840 | -
New Guinea | -306 | -
Borneo | -280 | -
The Header table part provides an opportunity to describe the data thatās presented. The subtitle
, which functions as a subtitle, is an optional part of the Header. We may also style the title
and subtitle
using Markdown! We do this by wrapping the values passed to title
or subtitle
with the md()
function. Here is an example with the table data truncated for brevity:
# Use markdown for the heading's `title` and `subtitle` to
-# add bold and italicized characters
-gt(islands_tbl[1:2,]) %>%
- tab_header(
- title = md("**Large Landmasses of the World**"),
- subtitle = md("The *top two* largest are presented")
- )
Large Landmasses of the World | -|
---|---|
The top two largest are presented | -|
name | -size | -
Asia | -16988 | -
Africa | -11506 | -
A source note can be added to the tableās footer through use of the tab_source_note()
function. It works in the same way as tab_header()
(it also allows for Markdown inputs) except it can be called multiple timesāeach invocation results in the addition of a source note.
# Display the `islands_tbl` data with a heading and
-# two source notes
-gt_tbl <-
- gt_tbl %>%
- tab_source_note(
- source_note = "Source: The World Almanac and Book of Facts, 1975, page 406."
- ) %>%
- tab_source_note(
- source_note = md("Reference: McNeil, D. R. (1977) *Interactive Data Analysis*. Wiley.")
- )
-
-# Show the gt Table
-gt_tbl
Large Landmasses of the World | -||
---|---|---|
The top ten largest are presented | -||
name | -size | -|
Asia | -16988 | -|
Africa | -11506 | -|
North America | -9390 | -|
South America | -6795 | -|
Antarctica | -5500 | -|
Europe | -3745 | -|
Australia | -2968 | -|
Greenland | -840 | -|
New Guinea | -306 | -|
Borneo | -280 | -|
Source: The World Almanac and Book of Facts, 1975, page 406. | -||
Reference: McNeil, D. R. (1977) Interactive Data Analysis. Wiley. | -
Footnotes live inside the Footer part and their reference glyphs are attached to cell data. Footnotes are added with the tab_footnote()
function. The helper function cells_data()
can be used with the location
argument to specify which data cells should be the target of the footnote. The cells_data()
helper has the two arguments columns
and rows
. For each of these, we can supply (1) a vector of colnames or rownames, (2) a vector of column/row indices, (3) bare column names wrapped in vars()
or row labels within c()
, or (4) a select helper function (starts_with()
, ends_with()
, contains()
, matches()
, one_of()
, and everything()
). For rows
specifically, we can use a conditional statement with column names as variables (e.g., size > 15000
).
Here is a simple example on how a footnotes can be added to a table cell. Letās add a footnote that references the North America
and South America
cells in the name
column:
# Add footnotes (the same text) to two different
-# cell; data cells are targeted with `data_cells()`
-gt_tbl <-
- gt_tbl %>%
- tab_footnote(
- footnote = "The Americas.",
- locations = cells_data(
- columns = vars(name),
- rows = 3:4)
- )
-
-# Show the gt Table
-gt_tbl
Large Landmasses of the World | -||
---|---|---|
The top ten largest are presented | -||
name | -size | -|
Asia | -16988 | -|
Africa | -11506 | -|
North America1 - | -9390 | -|
South America1 - | -6795 | -|
Antarctica | -5500 | -|
Europe | -3745 | -|
Australia | -2968 | -|
Greenland | -840 | -|
New Guinea | -306 | -|
Borneo | -280 | -|
Source: The World Almanac and Book of Facts, 1975, page 406. | -||
Reference: McNeil, D. R. (1977) Interactive Data Analysis. Wiley. | -||
-1 The Americas. | -
Here is a slightly more complex example of adding footnotes that use expressions in rows
to help target cells in a column by the underlying data in islands_tbl
. First, a set of dplyr statements obtains the name of the āislandā by largest landmass. This is assigned to the largest
object and is used in the first tab_footnote()
call that targets the cell in the size
column that is next to a name
value that is stored in largest
(āAsiaā). The second tab_footnote()
is similar except we are supplying a conditional statement that gets the lowest population.
# Determine the row that contains the
-# largest landmass ('Asia')
-largest <-
- islands_tbl %>%
- arrange(desc(size)) %>%
- slice(1) %>%
- pull(name)
-
-# Create two additional footnotes, using the
-# `columns` and `where` arguments of `data_cells()`
-gt_tbl <-
- gt_tbl %>%
- tab_footnote(
- footnote = md("The **largest** by area."),
- locations = cells_data(
- columns = vars(size),
- rows = name == largest)
- ) %>%
- tab_footnote(
- footnote = "The lowest by population.",
- locations = cells_data(
- columns = vars(size),
- rows = size == min(size))
- )
-
-# Show the gt Table
-gt_tbl
Large Landmasses of the World | -||
---|---|---|
The top ten largest are presented | -||
name | -size | -|
Asia | -169881 - | -|
Africa | -11506 | -|
North America2 - | -9390 | -|
South America2 - | -6795 | -|
Antarctica | -5500 | -|
Europe | -3745 | -|
Australia | -2968 | -|
Greenland | -840 | -|
New Guinea | -306 | -|
Borneo | -2803 - | -|
Source: The World Almanac and Book of Facts, 1975, page 406. | -||
Reference: McNeil, D. R. (1977) Interactive Data Analysis. Wiley. | -||
-1 The largest by area. 2 The Americas. 3 The lowest by population. |
-
We were able to supply the reference locations in the table by using the cells_data()
helper function and supplying the necessary targeting through the columns
and rows
arguments. Other cells_*()
functions have similar interfaces and they allow us to target cells in different parts of the table.
The Stub is the area to the left in a table that contains row labels, and may contain row group labels, and summary labels. Those subparts can be grouped in a sequence of row groups. The Stub Head provides a location for a label that describes the Stub. The Stub is optional since there are cases where a Stub wouldnāt be useful (e.g., the display tables presented above were just fine without a Stub).
-An easy way to generate a Stub part is by specifying a stub column in the gt()
function with the rowname_col
argument. Alternatively, we can have an input dataset with a column named rowname
āthis magic column will signal to gt that that column should be used as the stub, making row labels. Letās add a stub with our islands_tbl
dataset by modifying the call to gt()
:
# Create a gt table showing ten of the
-# largest islands in the world; this
-# time with a stub
-gt_tbl <-
- islands_tbl %>%
- gt(rowname_col = "name")
-
-# Show the gt Table
-gt_tbl
- | size | -
---|---|
Asia | -16988 | -
Africa | -11506 | -
North America | -9390 | -
South America | -6795 | -
Antarctica | -5500 | -
Europe | -3745 | -
Australia | -2968 | -
Greenland | -840 | -
New Guinea | -306 | -
Borneo | -280 | -
Notice that the landmass names are off the the left in an unstriped area? Thatās the stub. We can apply whatās known as a stubhead label. This label can be added with the tab_stubhead_label()
function:
# Generate a simple table with a stub
-# and add a stubhead label
-gt_tbl <-
- gt_tbl %>%
- tab_stubhead_label(label = "landmass")
-
-# Show the gt Table
-gt_tbl
landmass | -size | -
---|---|
Asia | -16988 | -
Africa | -11506 | -
North America | -9390 | -
South America | -6795 | -
Antarctica | -5500 | -
Europe | -3745 | -
Australia | -2968 | -
Greenland | -840 | -
New Guinea | -306 | -
Borneo | -280 | -
A very important thing to note here is that the table now has one column. Before, when there was no stub, two columns were present (with column labels name
and size
) but now column number 1
(the only column) is size
.
To apply our table parts as before (up to and including the footnotes) we use the following statements:
-# Display the `islands_tbl` data with a stub,
-# a heading, source notes, and footnotes
-gt_tbl <-
- gt_tbl %>%
- tab_header(
- title = "Large Landmasses of the World",
- subtitle = "The top ten largest are presented"
- ) %>%
- tab_source_note(
- source_note = "Source: The World Almanac and Book of Facts, 1975, page 406."
- ) %>%
- tab_source_note(
- source_note = md("Reference: McNeil, D. R. (1977) *Interactive Data Analysis*. Wiley.")
- ) %>%
- tab_footnote(
- footnote = md("The **largest** by area."),
- locations = cells_data(
- columns = vars(size),
- rows = largest)
- ) %>%
- tab_footnote(
- footnote = "The lowest by population.",
- locations = cells_data(
- columns = vars(size),
- rows = contains("arc"))
- )
-
-# Show the gt Table
-gt_tbl
Large Landmasses of the World | -||
---|---|---|
The top ten largest are presented | -||
landmass | -size | -|
Asia | -169881 - | -|
Africa | -11506 | -|
North America | -9390 | -|
South America | -6795 | -|
Antarctica | -55002 - | -|
Europe | -3745 | -|
Australia | -2968 | -|
Greenland | -840 | -|
New Guinea | -306 | -|
Borneo | -280 | -|
Source: The World Almanac and Book of Facts, 1975, page 406. | -||
Reference: McNeil, D. R. (1977) Interactive Data Analysis. Wiley. | -||
-1 The largest by area. 2 The lowest by population. |
-
Letās incorporate row groups into the display table. This divides rows into groups, creating row groups, and results in a display of a row group labels right above the each group. This can be easily done with a table containing row labels. We can make a new row group with each call of the tab_row_group()
function. The inputs are group names in the group
argument, and row references in the rows
argument. We can use any of the strategies to reference rows as we did we footnotes (e.g., vectors of names/indices, select helpers, etc.).
Here we will create three row groups (with row group labels continent
, country
, and subregion
) to have a grouping of rows.
# Create three row groups with the
-# `tab_row_group()` function
-gt_tbl <-
- gt_tbl %>%
- tab_row_group(
- group = "continent",
- rows = 1:6
- ) %>%
- tab_row_group(
- group = "country",
- rows = c("Australia", "Greenland")
- ) %>%
- tab_row_group(
- group = "subregion",
- rows = c("New Guinea", "Borneo")
- )
-
-# Show the gt Table
-gt_tbl
-#> Warning in min(rows_matched): no non-missing arguments to min; returning
-#> Inf
-#> Warning in max(rows_matched): no non-missing arguments to max; returning -
-#> Inf
Large Landmasses of the World | -||
---|---|---|
The top ten largest are presented | -||
landmass | -size | -|
continent | -||
Asia | -169881 - | -|
Africa | -11506 | -|
North America | -9390 | -|
South America | -6795 | -|
Antarctica | -55002 - | -|
Europe | -3745 | -|
country | -||
Australia | -2968 | -|
Greenland | -840 | -|
subregion | -||
New Guinea | -306 | -|
Borneo | -280 | -|
Source: The World Almanac and Book of Facts, 1975, page 406. | -||
Reference: McNeil, D. R. (1977) Interactive Data Analysis. Wiley. | -||
-1 The largest by area. 2 The lowest by population. |
-
Three row groups have been made since there are three unique categories under groupname
. Across the top of each row group is the row group label contained in a separate row (these cut across the field and they contain nothing but the row group label). A rearrangement of rows is carried out to ensure each of the rows is collected within the appropriate row groups.
Having groups of rows in row groups is a great way to present information. Including data summaries particular to each group is a natural extension of this idea. This process of adding summary rows with summary labels is covered in a separate article (Creating Summary Lines).
-Another way to make row groups is to have the magic column groupname
present in the input data table. For our above example with islands_tbl
, a groupname
column with the categories continent
, country
, and subregion
in the appropriate rows would produce row groups automatically (i.e., there would be no need to use the tab_row_group()
statements). This strategy of supplying group names in a groupname
column name can sometimes be advantageous since we can rely on functions such as those available in dplyr to generate the categories (e.g., using case_when()
or if_else()
).
The tableās Column Labels part contains, at a minimum, columns and their column labels. The last example had a single column: size
. Just as in the Stub, we can create groupings called spanner columns that encompass one or more columns.
To better demonstrate how Column Labels work and are displayed, letās use an input data table with more columns. In this case, that input table will be airquality
. It has the following columns:
Ozone
: mean ground-level ozone in parts per billion by volume (ppbV), measured between 13:00 and 15:00Solar.R
: solar radiation in Langley units (cal/m2), measured between 08:00 and noonWind
: mean wind speed in miles per hour (mph)Temp
: maximum daily air temperature in degrees Fahrenheit (Ā°F)Month
, Day
: the numeric month and day of month for the recordWe know that all measurements took place in 1973, so a year
column will be added to the dataset before it is passed to gt()
.
Letās organize the time information under a Time
spanner column label, and put the other columns under a Measurement
spanner column label. We can do this with the tab_spanner()
function.
# Modify the `airquality` dataset by adding the year
-# of the measurements (1973) and limiting to 10 rows
-airquality_m <-
- airquality %>%
- mutate(Year = 1973L) %>%
- slice(1:10)
-
-# Create a display table using the `airquality`
-# dataset; arrange columns into groups
-gt_tbl <-
- gt(data = airquality_m) %>%
- tab_header(
- title = "New York Air Quality Measurements",
- subtitle = "Daily measurements in New York City (May 1-10, 1973)"
- ) %>%
- tab_spanner(
- label = "Time",
- columns = vars(Year, Month, Day)
- ) %>%
- tab_spanner(
- label = "Measurement",
- columns = vars(Ozone, Solar.R, Wind, Temp)
- )
-
-# Show the gt Table
-gt_tbl
New York Air Quality Measurements | -||||||
---|---|---|---|---|---|---|
Daily measurements in New York City (May 1-10, 1973) | -||||||
Measurement | -Time | -|||||
Ozone | -Solar.R | -Wind | -Temp | -Month | -Day | -Year | -
41 | -190 | -7.4 | -67 | -5 | -1 | -1973 | -
36 | -118 | -8.0 | -72 | -5 | -2 | -1973 | -
12 | -149 | -12.6 | -74 | -5 | -3 | -1973 | -
18 | -313 | -11.5 | -62 | -5 | -4 | -1973 | -
NA | -NA | -14.3 | -56 | -5 | -5 | -1973 | -
28 | -NA | -14.9 | -66 | -5 | -6 | -1973 | -
23 | -299 | -8.6 | -65 | -5 | -7 | -1973 | -
19 | -99 | -13.8 | -59 | -5 | -8 | -1973 | -
8 | -19 | -20.1 | -61 | -5 | -9 | -1973 | -
NA | -194 | -8.6 | -69 | -5 | -10 | -1973 | -
We can do two more things to make this presentable:
-Time
columns to the beginning of the series (using cols_move_to_start()
)cols_label()
)Letās do both of these things in the next example.
-# Move the time-based columns to the start of
-# the column series; modify the column labels of
-# the measurement-based columns
-gt_tbl <-
- gt_tbl %>%
- cols_move_to_start(
- columns = vars(Year, Month, Day)
- ) %>%
- cols_label(
- Ozone = html("Ozone,<br>ppbV"),
- Solar.R = html("Solar R.,<br>cal/m<sup>2</sup>"),
- Wind = html("Wind,<br>mph"),
- Temp = html("Temp,<br>°F")
- )
-
-# Show the gt Table
-gt_tbl
New York Air Quality Measurements | -||||||
---|---|---|---|---|---|---|
Daily measurements in New York City (May 1-10, 1973) | -||||||
Time | -Measurement | -|||||
Year | -Month | -Day | -Ozone, ppbV |
-Solar R., cal/m2 - |
-Wind, mph |
-Temp, Ā°F |
-
1973 | -5 | -1 | -41 | -190 | -7.4 | -67 | -
1973 | -5 | -2 | -36 | -118 | -8.0 | -72 | -
1973 | -5 | -3 | -12 | -149 | -12.6 | -74 | -
1973 | -5 | -4 | -18 | -313 | -11.5 | -62 | -
1973 | -5 | -5 | -NA | -NA | -14.3 | -56 | -
1973 | -5 | -6 | -28 | -NA | -14.9 | -66 | -
1973 | -5 | -7 | -23 | -299 | -8.6 | -65 | -
1973 | -5 | -8 | -19 | -99 | -13.8 | -59 | -
1973 | -5 | -9 | -8 | -19 | -20.1 | -61 | -
1973 | -5 | -10 | -NA | -194 | -8.6 | -69 | -
Note that even though columns were moved using cols_move_to_start()
, the spanner column labels still spanned above the correct column labels. There are a number of functions that gt provides to move columns, including cols_move()
, cols_move_to_end()
; thereās even a function to hide columns: cols_hide()
.
Multiple columns can be renamed in a single use of cols_label()
. Further to this, the helper functions md()
and html()
can be used to create column labels with additional styling. In the above example, we provided column labels as HTML so that we can insert linebreaks with <br>
, insert a superscripted 2
(with <sup>2</sup>
), and insert a degree symbol as an HTML entity (°
).
vignettes/creating-summary-lines.Rmd
- creating-summary-lines.Rmd
Tables with summary data are quite common and naturally occur with alarming regularity. We can use gt to produce such summary components. These summary rows are automatically inserted within the relevant row groups, where each summary row is the result of a different aggregation function.
-To most easily insert the necessary summary rows, we need to ensure that some preparatory work is done. The key change to the input data table should be to have a groupname
column present, with categorical group names for each grouping. The following example data table contains both groupname
and rowname
columns, along with two data columns (named value_1
and value_2
). Having the magic column names groupname
and rowname
will signal to gt that they should be used to form a table stub where groupname
collects rows into a row group (furnishing a group heading row above), and rowname
provides row labels within each row group. Here is a diagram showing the restructuring:
The incoming data table for the purpose of the first example will be created using dplyr::tribble()
:
# Create a table that creates a stub and
-# row groups by virtue of having `groupname`
-# and `rowname` columns
-tbl <-
- dplyr::tribble(
- ~groupname, ~rowname, ~value_1, ~value_2,
- "A", "1", 235.6, 260.1,
- "A", "2", 184.3, 84.4,
- "A", "3", 342.3, 126.3,
- "A", "4", 234.9, 83.0,
- "B", "1", 190.9, 832.5,
- "B", "2", 743.3, 281.2,
- "B", "3", 252.3, 732.5,
- "B", "4", 344.7, 546.1,
- "C", "1", 197.2, 818.0,
- "C", "2", 284.3, 394.4,
- )
There are three groups in this data table: A
, B
, and C
. The presence of the groupname
column will tell gt to partition the stub into three row groups. This is how the gt display table appears after simply providing tbl
to gt()
:
- | value_1 | -value_2 | -
---|---|---|
A | -||
1 | -235.6 | -260.1 | -
2 | -184.3 | -84.4 | -
3 | -342.3 | -126.3 | -
4 | -234.9 | -83.0 | -
B | -||
1 | -190.9 | -832.5 | -
2 | -743.3 | -281.2 | -
3 | -252.3 | -732.5 | -
4 | -344.7 | -546.1 | -
C | -||
1 | -197.2 | -818.0 | -
2 | -284.3 | -394.4 | -
Summaries by row group can be generated by using the summary_rows()
function. Thereās a lot of control in how the summaries are conducted and formatted. First of all, we can choose which groups will receive summary rows (the rows appear at the bottom of each row group). This optional choice of groups can be made using the groups
argument (providing a vector of group names). Secondly, we can choose which columns should be included in the summary with the columns
argument (in this case, wrapping column names in vars()
). If we provide nothing to groups
, then all groups will receive summary data for the selected columns
.
To make any sort of summary, we need to use functions that will perform the aggregation. We can provide base functions such as mean()
, sum()
, min()
, max()
, and more, within a list()
or c()
. Each function provided will result in a summary row for each group.
Because each function will yield a row, we need to be able to identify that row. So, each summary row will receive a summary row label. We can provide our preferred names by naming the functions within the list or c()
(e.g, list(average = "mean", total = "sum", SD = "sd")
or c("mean", total = "sum", stdev = "sd")
). If names arenāt supplied, then gt will derive names from the functions supplied and make the names unique.
Now that the summary_rows()
function has been somewhat explained, letās look at how we can get summary rows for the tbl
table:
# Create a gt table with summary rows for
-# `value_1` in the `A` and `B` row groups;
-# three summary rows are made per group
-# (one for each function in `fns`)
-gt(tbl) %>%
- summary_rows(
- groups = c("A", "B"),
- columns = vars(value_1),
- fns = list("mean", "sum", "sd")
- )
- | value_1 | -value_2 | -
---|---|---|
A | -||
1 | -235.6 | -260.1 | -
2 | -184.3 | -84.4 | -
3 | -342.3 | -126.3 | -
4 | -234.9 | -83.0 | -
mean | -249.28 | -ā | -
sum | -997.10 | -ā | -
sd | -66.51 | -ā | -
B | -||
1 | -190.9 | -832.5 | -
2 | -743.3 | -281.2 | -
3 | -252.3 | -732.5 | -
4 | -344.7 | -546.1 | -
mean | -382.80 | -ā | -
sum | -1,531.20 | -ā | -
sd | -248.51 | -ā | -
C | -||
1 | -197.2 | -818.0 | -
2 | -284.3 | -394.4 | -
Here we see that summary rows were created for the A
and B
groups (group C
has no summary lines in its row group). It was specified in columns
that only the value_1
column should be evaluated and, indeed, the value_2
column shows no values whatsoever within the summary rows.
There is some flexibility in how we supply aggregation functions to summary_rows()
. Itās sometimes sufficient to supply function names enclosed in quotes (e.g., list("mean", "sum", "sd")
) but the next section will demonstrate a more advanced method for supplying these functions (where we donāt have to rely on function defaults). If we already have a vector of function names that use all of the default arguments within those functions, we can pass this directly to fns
. This is nice if we want to build a common named vector of function names and summary labels. Hereās an example that does just that:
# Define a named vector of function names
-# and summary row labels
-fns_labels <- c(average = "mean", total = "sum", `std dev` = "sd")
-
-# Use `fns_labels` in `fns`
-gt(tbl) %>%
- summary_rows(
- columns = vars(value_1),
- fns = fns_labels
- )
- | value_1 | -value_2 | -
---|---|---|
A | -||
1 | -235.6 | -260.1 | -
2 | -184.3 | -84.4 | -
3 | -342.3 | -126.3 | -
4 | -234.9 | -83.0 | -
average | -249.28 | -ā | -
total | -997.10 | -ā | -
std dev | -66.51 | -ā | -
B | -||
1 | -190.9 | -832.5 | -
2 | -743.3 | -281.2 | -
3 | -252.3 | -732.5 | -
4 | -344.7 | -546.1 | -
average | -382.80 | -ā | -
total | -1,531.20 | -ā | -
std dev | -248.51 | -ā | -
C | -||
1 | -197.2 | -818.0 | -
2 | -284.3 | -394.4 | -
average | -240.75 | -ā | -
total | -481.50 | -ā | -
std dev | -61.59 | -ā | -
Sometimes we want to use functions with some parameters set. The earlier example using list("mean", "sum", "sd")
will break down if we have NA
values in our data and we want to exclude those by using na.rm = TRUE
. In this case we can provide a call to a function with a right-hand side (RHS) formula shortcut, having .
serve as the data values. Here is an example where we modify our tbl
to include some NA
values (calling it tbl_na
) and then changing the contents of the list()
āusing c()
will work just as wellāas calls to functions:
# Create an alternate version of the
-# `tbl` data frame that contains NAs
-tbl_na <-
- tbl %>%
- mutate(value_1 = case_when(
- value_1 >= 300 ~ NA_real_,
- value_1 < 300 ~ value_1)
- ) %>%
- mutate(value_2 = case_when(
- value_2 >= 600 ~ NA_real_,
- value_2 < 600 ~ value_2)
- )
-
-# Create summary rows from `tbl_na` within
-# groups `A` and `B` but provide the
-# aggregation functions as formulas so that
-# we can modify the default options
-gt(tbl_na) %>%
- summary_rows(
- groups = c("A", "B"),
- columns = vars(value_1, value_2),
- fns = list(
- average = ~mean(., na.rm = TRUE),
- sum = ~sum(., na.rm = TRUE),
- `std dev` = ~sd(., na.rm = TRUE))
- )
- | value_1 | -value_2 | -
---|---|---|
A | -||
1 | -235.6 | -260.1 | -
2 | -184.3 | -84.4 | -
3 | -NA | -126.3 | -
4 | -234.9 | -83.0 | -
average | -218.27 | -138.45 | -
sum | -654.80 | -553.80 | -
std dev | -29.42 | -83.55 | -
B | -||
1 | -190.9 | -NA | -
2 | -NA | -281.2 | -
3 | -252.3 | -NA | -
4 | -NA | -546.1 | -
average | -221.60 | -413.65 | -
sum | -443.20 | -827.30 | -
std dev | -43.42 | -187.31 | -
C | -||
1 | -197.2 | -NA | -
2 | -284.3 | -394.4 | -
The input to fns
is very permissive in regard to how the functions are defined. It is entirely valid to provide functions in the various forms shown earlier such that list("sum", ~mean(., na.rm = TRUE), SD = "sd")
will be correctly interpreted.
Using summary_rows()
to generate a summary is, in effect, creating new data and thus we need some means to format the new summary row data. We can use the formatter
option to supply a formatting function to handle the formatting of the summary row data. Thankfully, we have a collection of formatting functions available in the package (i.e., all of the fmt_*()
functions). The default for formatter
is set to fmt_number
which is a sensible default for many scenarios. The setting of argument values for a particular formatter can be done in the ...
area of the function call.
Letās start with an example where we format the summary row data using fmt_number
as the formatter. The fmt_number()
function several arguments to which we can pass values (decimals
, drop_trailing_zeros
, negative_val
, locale
, etc.). Here, we will provide decimals = 3
to augment fmt_number()
:
# Use the formatter options in `...` to
-# provide values to `fmt_number`
-gt(tbl) %>%
- summary_rows(
- groups = "A",
- columns = vars(value_1, value_2),
- fns = c("mean", "sum", "min", "max"),
- formatter = fmt_number,
- decimals = 3
- )
- | value_1 | -value_2 | -
---|---|---|
A | -||
1 | -235.6 | -260.1 | -
2 | -184.3 | -84.4 | -
3 | -342.3 | -126.3 | -
4 | -234.9 | -83.0 | -
mean | -249.275 | -138.450 | -
sum | -997.100 | -553.800 | -
min | -184.300 | -83.000 | -
max | -342.300 | -260.100 | -
B | -||
1 | -190.9 | -832.5 | -
2 | -743.3 | -281.2 | -
3 | -252.3 | -732.5 | -
4 | -344.7 | -546.1 | -
C | -||
1 | -197.2 | -818.0 | -
2 | -284.3 | -394.4 | -
We can also store these argument values as local variables and pass them in both separate fmt_number()
calls and then to a summary_rows()
calls with fmt_number()
used as the formatter. This is useful for standardizing formatting parameters across different table cell types.
# Provide common formatting parameters to a list
-# object named `formats`; the number of decimal
-# places will be `2` and the locale is "fr_BE"
-formats <- list(decimals = 2, locale = "fr_BE")
-
-# Provide the formatting options from `formats` to
-# all row data in all columns, and, to the summary
-# row data
-gt(tbl) %>%
- fmt_number(
- columns = vars(value_1, value_2),
- decimals = formats$decimals,
- locale = formats$locale
- ) %>%
- summary_rows(
- groups = "A",
- columns = vars(value_1, value_2),
- fns = list("mean", "sum", "min", "max"),
- formatter = fmt_number,
- decimals = formats$decimals,
- locale = formats$locale
- )
- | value_1 | -value_2 | -
---|---|---|
A | -||
1 | -235,60 | -260,10 | -
2 | -184,30 | -84,40 | -
3 | -342,30 | -126,30 | -
4 | -234,90 | -83,00 | -
mean | -249,28 | -138,45 | -
sum | -997,10 | -553,80 | -
min | -184,30 | -83,00 | -
max | -342,30 | -260,10 | -
B | -||
1 | -190,90 | -832,50 | -
2 | -743,30 | -281,20 | -
3 | -252,30 | -732,50 | -
4 | -344,70 | -546,10 | -
C | -||
1 | -197,20 | -818,00 | -
2 | -284,30 | -394,40 | -
For a reproducible workflow, we do not want to have situations where any data created or modified cannot be accessed. While having summarized values be created in a gt pipeline presents advantages to readability and intent of analysis, it is recognized that the output table itself is essentially āread onlyā, as the input data undergoes processing and movement to an entirely different format.
-However, the object created still contains data and we can obtain the summary data from a gt table object using the extract_summary()
function. Taking the gt_summary
object, we get a data frame containing the summary data while preserving the correct data types:
# Create a gt table with summary rows and
-# assign it to `gt_object`
-gt_object <-
- gt(tbl) %>%
- summary_rows(
- groups = c("A", "B"),
- columns = vars(value_1, value_2),
- fns = list("mean", "sum", "sd")
- )
# Extract the summary data from `gt_object`
-# to a data frame object
-summary_list <- gt_object %>% extract_summary()
-
-# This is a list with two elements named
-# `A` and `B` (matches the summary groups)
-names(summary_list)
-#> [1] "A" "B"
# Print out the summary for the `A` group
-summary_list[["A"]]
-#> # A tibble: 3 x 4
-#> groupname rowname value_1 value_2
-#> <chr> <chr> <dbl> <dbl>
-#> 1 A mean 249. 138.
-#> 2 A sum 997. 554.
-#> 3 A sd 66.5 83.6
# Print out the summary for the `B` group
-summary_list[["B"]]
-#> # A tibble: 3 x 4
-#> groupname rowname value_1 value_2
-#> <chr> <chr> <dbl> <dbl>
-#> 1 B mean 383. 598.
-#> 2 B sum 1531. 2392.
-#> 3 B sd 249. 242.
The output data frames within the list always contain the groupname
and rowname
columns. The groupname
column is filled with the name of the stub group given in summary_rows()
. The rowname
column contains the descriptive stub labels for the summary rows (recall that values are either supplied explicitly in summary_rows()
, or, are generated from the function names). The remaining columns are from the original dataset.
The output data frame from extract_summary()
can be reintroduced to a reproducible workflow and serve as downstream inputs or undergo validation. Perhaps interestingly, the output data frame is structured in a way that facilitates direct input to gt()
(i.e., has the magic groupname
and rowname
columns). This can produce a new, standalone summary table where the summary rows are now data rows:
# Take the `gt_object`, which has a list of
-# summary data frames, combine them with
-# `do.call(bind_rows, ...)`, input that into
-# `gt()`, and format all of the numeric values
-do.call(
- dplyr::bind_rows,
- gt_object %>% extract_summary()
-) %>%
- gt() %>%
- fmt_number(
- columns = vars(value_1, value_2),
- decimals = 3
- )
- | value_1 | -value_2 | -
---|---|---|
A | -||
mean | -249.275 | -138.450 | -
sum | -997.100 | -553.800 | -
sd | -66.506 | -83.551 | -
B | -||
mean | -382.800 | -598.075 | -
sum | -1,531.200 | -2,392.300 | -
sd | -248.507 | -242.306 | -
While many of the functions available in base R and within packages are useful as aggregate functions, we may occasionally have need to create our own custom functions. The only things to keep in mind are to ensure that a vector of values is the main input, and, a single value is returned. The return value can be most any class (e.g., numeric
, character
, logical
) and itās the formatter
function that will handle any custom formatting while also converting to character
.
Here, weāll define a function that takes a vector of numeric values and outputs the two highest values (sorted low to high) above a threshold
value. The output from this function is always a formatted character
string.
# Define a function that gives the
-# highest two values above a threshold
-agg_highest_two_above_value <- function(x, threshold) {
-
- # Get sorted values above threshold value
- values <- sort(round(x[x >= threshold], 2))
-
- # Return character string with 2 highest values above threshold
- if (length(values) == 0) {
- return(paste0("No values above ", threshold))
- } else {
- return(
- paste(
- formatC(
- tail(
- sort(round(x[x > threshold], 2)), 2),
- format = "f", digits = 2), collapse = ", "))
- }
-}
-
-# Let's test this function with some values
-agg_highest_two_above_value(
- x = c(0.73, 0.93, 0.75, 0.86, 0.23, 0.81),
- threshold = 0.8
-)
-#> [1] "0.86, 0.93"
Because this is character value thatās returned, we donāt need formatting functions like fmt_number()
, fmt_percent()
, etc. However, a useful formatter (and we do need some formatter) is the fmt_passthrough()
function. Like the name suggests, it to great extent passes values through but formats as character
(like all the fmt_*()
function do) and it provides the option to decorate the output with a pattern
. Letās have a look at how the agg_highest_two_above_value()
function can be used with the fmt_passthrough()
formatter function.
# Create a gt table with summary rows for
-# `value_1` & `value_2`; the custom function
-# is being used with a threshold of `150`; the
-# `fmt_passthrough` allows for minimal
-# formatting of the aggregate values
-summary_tbl <-
- gt(tbl_na) %>%
- summary_rows(
- columns = vars(value_1, value_2),
- fns = list(
- high = ~agg_highest_two_above_value(., 150)),
- formatter = fmt_passthrough,
- pattern = "({x})"
- ) %>%
- fmt_missing(columns = vars(value_1, value_2))
-
-summary_tbl
- | value_1 | -value_2 | -
---|---|---|
A | -||
1 | -235.6 | -260.1 | -
2 | -184.3 | -84.4 | -
3 | -ā | -126.3 | -
4 | -234.9 | -83 | -
high | -(234.90, 235.60) | -(260.10) | -
B | -||
1 | -190.9 | -ā | -
2 | -ā | -281.2 | -
3 | -252.3 | -ā | -
4 | -ā | -546.1 | -
high | -(190.90, 252.30) | -(281.20, 546.10) | -
C | -||
1 | -197.2 | -ā | -
2 | -284.3 | -394.4 | -
high | -(197.20, 284.30) | -(394.40) | -
We can extract the summary data from the summary_tbl
object. Note that columns value_1
and value_2
are classed as character since it was character outputs that were generated by the agg_highest_two_above_value()
function.
summary_tbl %>%
- extract_summary() %>%
- str()
-#> List of 3
-#> $ A:Classes 'tbl_df', 'tbl' and 'data.frame': 1 obs. of 4 variables:
-#> ..$ groupname: chr "A"
-#> ..$ rowname : chr "high"
-#> ..$ value_1 : chr "234.90, 235.60"
-#> ..$ value_2 : chr "260.10"
-#> $ B:Classes 'tbl_df', 'tbl' and 'data.frame': 1 obs. of 4 variables:
-#> ..$ groupname: chr "B"
-#> ..$ rowname : chr "high"
-#> ..$ value_1 : chr "190.90, 252.30"
-#> ..$ value_2 : chr "281.20, 546.10"
-#> $ C:Classes 'tbl_df', 'tbl' and 'data.frame': 1 obs. of 4 variables:
-#> ..$ groupname: chr "C"
-#> ..$ rowname : chr "high"
-#> ..$ value_1 : chr "197.20, 284.30"
-#> ..$ value_2 : chr "394.40"
Suppose we have data across columns that should be summarized in the same way (i.e., common aggregate functions) but formatted differently (e.g., decimal notation, scientific notation, percentages, etc.). For each type of formatting, we need to call summary_rows()
, however, we can employ certain strategies to make the code a bit more succinct while doing so.
Letās start with a new data table. This table contains groupname
and rowname
columns, which making using summary_rows()
possible, along with large
, medium
, and small
data columns, all containing numeric values.
tbl_2 <-
- dplyr::tribble(
- ~groupname, ~rowname, ~large, ~medium, ~small,
- "A", "1", 235342.6, 342.2, 0.34,
- "A", "2", 184123.0, 971.7, 0.23,
- "A", "3", 342622.3, 392.6, 0.73,
- "A", "4", 234353.9, 684.5, 0.93,
- "B", "1", 190983.4, 328.0, 0.35,
- "B", "2", 748250.3, 671.3, 0.98,
- "B", "3", 252781.3, 934.2, 0.74,
- "B", "4", 344030.7, 673.3, 0.27,
- )
-
-tbl_2
-#> # A tibble: 8 x 5
-#> groupname rowname large medium small
-#> <chr> <chr> <dbl> <dbl> <dbl>
-#> 1 A 1 235343. 342. 0.34
-#> 2 A 2 184123 972. 0.23
-#> 3 A 3 342622. 393. 0.73
-#> 4 A 4 234354. 684. 0.93
-#> 5 B 1 190983. 328 0.35
-#> 6 B 2 748250. 671. 0.98
-#> 7 B 3 252781. 934. 0.74
-#> 8 B 4 344031. 673. 0.27
Here, we would like to apply a different format (both to the data rows and to the summary rows) across the three columns. We can store formatting options to three different list objects (large_fmts
, medium_fmts
, and small_fmts
) and use the stored values in the gt pipeline.
# Store formatting options in list objects
-large_fmts <-
- list(
- columns = "large",
- formatter = fmt_scientific,
- options = list(decimals = 2)
- )
-
-medium_fmts <-
- list(
- columns = "medium",
- formatter = fmt_number,
- options = list(decimals = 2)
- )
-
-small_fmts <-
- list(
- columns = "small",
- formatter = fmt_percent,
- options = list(decimals = 5)
- )
-
-# Format the data rows, then, create summary rows
-# and format summary data for consistent output in
-# each column
-tbl_2 %>%
- gt() %>%
- fmt_scientific(columns = large_fmts$columns) %>%
- fmt_number(columns = medium_fmts$columns) %>%
- fmt_percent(columns = small_fmts$columns) %>%
- summary_rows(
- columns = large_fmts$columns,
- fns = c("sum", "mean", "sd"),
- formatter = large_fmts$formatter
- ) %>%
- summary_rows(
- columns = medium_fmts$columns,
- fns = c("sum", "mean", "sd"),
- formatter = medium_fmts$formatter
- ) %>%
- summary_rows(
- columns = small_fmts$columns,
- fns = c("sum", "mean", "sd"),
- formatter = small_fmts$formatter
- )
- | large | -medium | -small | -
---|---|---|---|
A | -|||
1 | -2.35 Ć 105 - | -342.20 | -34.00% | -
2 | -1.84 Ć 105 - | -971.70 | -23.00% | -
3 | -3.43 Ć 105 - | -392.60 | -73.00% | -
4 | -2.34 Ć 105 - | -684.50 | -93.00% | -
sum | -9.96 Ć 105 - | -2,391.00 | -223.00% | -
mean | -2.49 Ć 105 - | -597.75 | -55.75% | -
sd | -6.68 Ć 104 - | -291.41 | -32.82% | -
B | -|||
1 | -1.91 Ć 105 - | -328.00 | -35.00% | -
2 | -7.48 Ć 105 - | -671.30 | -98.00% | -
3 | -2.53 Ć 105 - | -934.20 | -74.00% | -
4 | -3.44 Ć 105 - | -673.30 | -27.00% | -
sum | -1.54 Ć 106 - | -2,606.80 | -234.00% | -
mean | -3.84 Ć 105 - | -651.70 | -58.50% | -
sd | -2.51 Ć 105 - | -248.62 | -33.39% | -
Passing in parameters like this is useful, especially if there are larger numbers of columns. Additionally, we can store formatting parameters outside of the gt()
pipeline and separate our concerns between data structuring and data formatting. The separation of styles and options into objects becomes more important if we intend to centralize formatting options for reuse.
Another thing to note in the above example is that even though multiple independent calls of summary_rows()
were made, summary data within common summary row names were āsquashedā together, thus avoiding the fragmentation of summary rows. Put another way, we donāt create additional summary rows from a group across separate calls if we are referencing the same summary row labels. If the summary row labels provided in fns
were to be different across columns, however, additional summary rows would be produced even if the types of data aggregations were to be functionally equivalent.
The gt package comes with six built-in datasets for experimenting with the gt API: countrypops
, sza
, gtcars
, sp500
, pizzaplace
, and exibble
. While each dataset has different subject matter, all of them will be used to develop gt examples with consistent syntax.
Each dataset is stored as a tibble, ranging from very small (like exibble
, an example tibble of 8 rows) to quite large in size (e.g., at nearly 50,000 rows: pizzaplace
). Larger datasets are typically impractical as gt output tables but they provide opportunities for demonstrating preprocessing using tidyverse tools like dplyr and tidyr (upstream of gtās gt()
entry point).
In many gt workflows, there will often be prep work like this where the creation of the input table and any salient information (e.g., metadata for footnotes) will be done alongside the preparation of the display table.
-In the next few examples, weāll show how tables can be created with each of these datasets. Each example will be preceded with a set of requirements that serve as a design brief. This planning stage can be very useful in your own work for the purpose of organization. The hope is that this collection of simple examples will inspire the creation of much more interesting display tables with gt.
-countrypops
-This dataset provides the total populations of 215 countries on a yearly basis, from 1960 to 2017. The source data comes from the World Bank, where it has been cleaned and tidied up for inclusion into this package. Each row contains a population value for a country in a given year, where NA
values for population
indicate that the country did not exist in that particular year.
The countrypops
dataset is a tibble with 12,470 rows and 5 variables. Here are explanations for each of the variables:
Column | -Type | -Description | -
---|---|---|
country_name | -chr | -Name of the country | -
country_code_2 | -chr | -The 2-letter ISO 3166-1 country code | -
country_code_3 | -chr | -The 3-letter ISO 3166-1 country code | -
year | -int | -The year for the population estimate | -
population | -int | -The population estimate, midway through the year | -
countrypops
ExampleThe table that weāll create from countrypops
will meet these requirements:
# Get vectors of 2-letter country codes for
-# each region of Oceania
-Australasia <- c("AU", "NZ")
-Melanesia <- c("NC", "PG", "SB", "VU")
-Micronesia <- c("FM", "GU", "KI", "MH", "MP", "NR", "PW")
-Polynesia <- c("PF", "WS", "TO", "TV")
-
-# Create a gt table based on a preprocessed `countrypops`
-countrypops %>%
- dplyr::filter(country_code_2 %in% c(
- Australasia, Melanesia, Micronesia, Polynesia)
- ) %>%
- dplyr::filter(year %in% c(1995, 2005, 2015)) %>%
- dplyr::mutate(region = case_when(
- country_code_2 %in% Australasia ~ "Australasia",
- country_code_2 %in% Melanesia ~ "Melanesia",
- country_code_2 %in% Micronesia ~ "Micronesia",
- country_code_2 %in% Polynesia ~ "Polynesia",
- )) %>%
- tidyr::spread(key = year, value = population) %>%
- dplyr::arrange(region, desc(`2015`)) %>%
- dplyr::select(-starts_with("country_code")) %>%
- gt(
- rowname_col = "country_name",
- groupname_col = "region"
- ) %>%
- tab_header(title = "Populations of Oceania's Countries in 1995, 2005, and 2015") %>%
- tab_spanner(
- label = "Total Population",
- columns = c("1995", "2005", "2015")
- ) %>%
- fmt_number(
- columns = TRUE,
- decimals = 0,
- use_seps = TRUE
- )
Populations of Oceania's Countries in 1995, 2005, and 2015 | -|||
---|---|---|---|
- | |||
- | Total Population | -||
1995 | -2005 | -2015 | -|
Australasia | -|||
Australia | -18,072,000 | -20,394,800 | -23,850,784 | -
New Zealand | -3,673,400 | -4,133,900 | -4,595,700 | -
Melanesia | -|||
Papua New Guinea | -4,894,276 | -6,314,709 | -7,919,825 | -
Solomon Islands | -359,225 | -469,885 | -587,482 | -
New Caledonia | -193,816 | -232,250 | -272,400 | -
Vanuatu | -168,235 | -209,370 | -264,603 | -
Micronesia | -|||
Guam | -145,561 | -158,402 | -161,797 | -
Kiribati | -77,730 | -92,325 | -112,407 | -
Micronesia (Federated States) | -107,556 | -106,196 | -104,433 | -
Northern Mariana Islands | -56,278 | -63,744 | -54,816 | -
Marshall Islands | -51,015 | -52,055 | -52,994 | -
Palau | -17,253 | -19,906 | -21,288 | -
Nauru | -9,969 | -10,114 | -12,475 | -
Polynesia | -|||
French Polynesia | -215,196 | -254,886 | -277,690 | -
Samoa | -170,157 | -179,929 | -193,759 | -
Tonga | -96,076 | -101,041 | -106,364 | -
Tuvalu | -9,230 | -10,027 | -11,001 | -
sza
-The solar zenith angle is one measure of the solar position. It can be thought of as āheightā of the sun in relation to an observer. A solar zenith angle of 0Ā° indicates that the sun is directly overhead (a different solar angle, the solar altitude angle, is 90Ā° in this instance). With the sun at the horizontal (e.g., during sunrise/sunset) we observe the solar zenith angle to be around 90Ā° (there is the matter of atmospheric refraction). During nighttime, solar zenith angles in the range of 90ā180 are possible (again, depending on the location of the observer).
-The sza
dataset has calculated values for the solar zenith angles every 30 minutes from 04:00 to 12:00 (true solar time). Temporally, these calculations are for the 1st of every month of the year. Spatially, the observer is located at somewhere along latitudes 20Ā°N, 30Ā°N, 40Ā°N, and 50Ā°N (because we are using true solar time, the longitude is unimportant). This is quite an extensive topic, and more information can be found by using ?sza
in the R console or by visiting this page.
The sza
dataset is a tibble with 816 rows and 4 variables. Here are explanations for each of the variables:
Column | -Type | -Description | -
---|---|---|
latitude | -dbl | -The latitude in decimal degrees for the observations | -
month | -fct | -The measurement month; all calculations where conducted for the first day of each month | -
tst | -chr | -The true solar time at the given latitude and date (first of month) for which the solar zenith angle is calculated | -
sza | -dbl | -The solar zenith angle in degrees, where NAs indicate that sunrise hadn't yet occurred by the tst value | -
sza
ExampleThe table that weāll create from sza
will meet these requirements:
latitude
columnNA
values from sza
column are to be removedtst
(true solar time) contain angles in degrees (from the sza
column)month
s as row labels in the stub☀
) symbol# Create a gt table based on a preprocessed `sza`
-sza %>%
- dplyr::filter(latitude == 20) %>%
- dplyr::select(-latitude) %>%
- dplyr::filter(!is.na(sza)) %>%
- tidyr::spread(key = "tst", value = sza) %>%
- gt(rowname_col = "month") %>%
- fmt_missing(
- columns = TRUE,
- missing_text = ""
- ) %>%
- tab_stubhead_label(label = html("month<br>(20°N)")) %>%
- tab_header(title = html("☀ Solar Zenith Angles ☀")) %>%
- tab_options(
- column_labels.font.size = "smaller",
- table.font.size = "smaller",
- row.padding = px(3)
- )
ā Solar Zenith Angles ā | -||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
- | ||||||||||||||
month (20Ā°N) |
-0530 | -0600 | -0630 | -0700 | -0730 | -0800 | -0830 | -0900 | -0930 | -1000 | -1030 | -1100 | -1130 | -1200 | -
jan | -- | - | - | 84.9 | -78.7 | -72.7 | -66.1 | -61.5 | -56.5 | -52.1 | -48.3 | -45.5 | -43.6 | -43 | -
feb | -- | - | 88.9 | -82.5 | -75.8 | -69.6 | -63.3 | -57.7 | -52.2 | -47.4 | -43.1 | -40 | -37.8 | -37.2 | -
mar | -- | - | 85.7 | -78.8 | -72 | -65.2 | -58.6 | -52.3 | -46.2 | -40.5 | -35.5 | -31.4 | -28.6 | -27.7 | -
apr | -- | 88.5 | -81.5 | -74.4 | -67.4 | -60.3 | -53.4 | -46.5 | -39.7 | -33.2 | -26.9 | -21.3 | -17.2 | -15.5 | -
may | -- | 85 | -78.2 | -71.2 | -64.3 | -57.2 | -50.2 | -43.2 | -36.1 | -29.1 | -26.1 | -15.2 | -8.8 | -5 | -
jun | -89.2 | -82.7 | -76 | -69.3 | -62.5 | -55.7 | -48.8 | -41.9 | -35 | -28.1 | -21.1 | -14.2 | -7.3 | -2 | -
jul | -88.8 | -82.3 | -75.7 | -69.1 | -62.3 | -55.5 | -48.7 | -41.8 | -35 | -28.1 | -21.2 | -14.3 | -7.7 | -3.1 | -
aug | -- | 83.8 | -77.1 | -70.2 | -63.3 | -56.4 | -49.4 | -42.4 | -35.4 | -28.3 | -21.3 | -14.3 | -7.3 | -1.9 | -
sep | -- | 87.2 | -80.2 | -73.2 | -66.1 | -59.1 | -52.1 | -45.1 | -38.1 | -31.3 | -24.7 | -18.6 | -13.7 | -11.6 | -
oct | -- | - | 84.1 | -77.1 | -70.2 | -63.3 | -56.5 | -49.9 | -43.5 | -37.5 | -32 | -27.4 | -24.3 | -23.1 | -
nov | -- | - | 87.8 | -81.3 | -74.5 | -68.3 | -61.8 | -56 | -50.2 | -45.3 | -40.7 | -37.4 | -35.1 | -34.4 | -
dec | -- | - | - | 84.3 | -78 | -71.8 | -66.1 | -60.5 | -55.6 | -50.9 | -47.2 | -44.2 | -42.4 | -41.8 | -
gtcars
-The gtcars
dataset takes off where mtcars
left off. It contains 47 cars from the 2014-2017 model years. Many of the gtcars
vehicles are grand tourers. Indeed, many of these provide the ability to cross an entire continent at speed and in comfort yet, when itās called for, they will allow you to experience driving thrills. The chassis and suspension are in most cases top-notch and supply superb handling and roadholding on all routes one would conceivably encounter during the grand touring experience. The two plus two (2 + 2) seating configuration is smartly designed to deliver comfort for a driver and passenger, adequate space for luggage, and have room to spare.
The gtcars
dataset is a tibble with 47 rows and 15 variables. Here are explanations for each of the variables:
Column | -Type | -Description | -
---|---|---|
mfr | -chr | -The name of the car manufacturer | -
model | -chr | -The car's model name | -
year | -int | -The car's model year | -
trim | -chr | -A short description of the car model's trim | -
bdy_style | -chr | -An identifier of the car's body style, which is either coupe, convertible, sedan, or hatchback | -
hp, hp_rpm | -int | -The car's horsepower and the associated RPM level | -
trq, trq_rpm | -int | -The car's torque and the associated RPM level | -
mpg_c, mpg_h | -int | -The miles per gallon fuel efficiency rating for city and highway driving | -
drivetrain | -chr | -The car's drivetrain which, for this dataset is either rwd (Rear Wheel Drive) or awd (All Wheel Drive) | -
trsmn | -chr | -The codified transmission type, where the number part is the number of gears; the car could have automatic transmission (a), manual transmission (m), an option to switch between both types (am), or, direct drive (dd) | -
ctry_origin | -chr | -The country name for where the vehicle manufacturer is headquartered | -
gtcars
ExampleThe table that weāll create from gtcars
will meet these requirements:
mfr
), the car model (model
), the drivetrain
, and the price (msrp
)drivetrain
textdrivetrain
abbreviations and that state the currency of the msrp
prices; ensure that the footnote glyphs are lowercase letters# Create a gt table based on a preprocessed `gtcars`
-gtcars %>%
- dplyr::filter(ctry_origin == "Germany") %>%
- dplyr::group_by(mfr) %>%
- dplyr::top_n(2, msrp) %>%
- dplyr::ungroup() %>%
- dplyr::select(mfr, model, drivetrain, msrp) %>%
- gt() %>%
- tab_header(title = "Select German Automobiles") %>%
- cols_merge(
- col_1 = "mfr",
- col_2 = "model"
- ) %>%
- text_transform(
- locations = cells_data(columns = vars(drivetrain)),
- fn = function(x) toupper(x)
- ) %>%
- fmt_currency(
- columns = vars(msrp),
- currency = "USD",
- decimals = 0,
- use_seps = TRUE
- ) %>%
- tab_footnote(
- footnote = "Prices in USD.",
- locations = cells_column_labels(columns = vars(msrp))
- ) %>%
- tab_footnote(
- footnote = "AWD = All Wheel Drive, RWD = Rear Wheel Drive.",
- locations = cells_column_labels(columns = vars(drivetrain))
- ) %>%
- tab_options(footnote.glyph = letters) %>%
- cols_label(
- mfr = "Car",
- drivetrain = "Drivetrain",
- msrp = "MSRP"
- )
Select German Automobiles | -||
---|---|---|
- | ||
Car | -Drivetraina - | -MSRPb - | -
BMW i8 | -AWD | -$140,700 | -
BMW M6 | -RWD | -$113,400 | -
Audi R8 | -AWD | -$115,900 | -
Audi S8 | -AWD | -$114,900 | -
Mercedes-Benz AMG GT | -RWD | -$129,900 | -
Mercedes-Benz SL-Class | -RWD | -$85,050 | -
Porsche 911 | -RWD | -$84,300 | -
Porsche Panamera | -RWD | -$78,100 | -
-a AWD = All Wheel Drive, RWD = Rear Wheel Drive. b Prices in USD. |
-
sp500
-The S&P 500 is a capitalization-weighted index of about 500 leading companies (where bigger companies have more influence within the index) that have common stock listed in either the NYSE or NASDAQ markets. The companies chosen are intended to provide representation of the U.S. economy. This index is a managed list (managed by S&P Dow Jones Indices LLC) with occasional changes of the constituent companies based on their performance and changes in the economy.
-There is daily S&P 500 data available in the sp500
dataset, with daily indicators (price statistics, volume
, etc.) from 1950 to 2015, inclusive. There are 16,607 rows in the dataset, and 7 variables:
Column | -Type | -Description | -
---|---|---|
date | -date | -The date expressed as `Date` values | -
open, high, low, close | -dbl | -The day's opening, high, low, and closing prices in USD; the close price is adjusted for splits | -
volume | -dbl | -The number of trades for the given `date` | -
adj_close | -dbl | -The close price adjusted for both dividends and splits | -
sp500
ExampleThe table that weāll create from sp500
will meet these requirements:
2010-06-02
to 2010-06-15
-adj_close
column wonāt be includeddate
column to appear as ā2 Jun 2010āopen
, high
, low
, close
) appear in USDvolume
will be shown as billions (with the B
suffix)close
price as appropriate# Define the start and end dates for the data range
-start_date <- "2010-06-02"
-end_date <- "2010-06-15"
-
-# The HTML decimal references for the black
-# up- and down-pointing triangles are: #9650 and #9660;
-# use an in-line style to apply color
-up_arrow <- "<span style=\"color:green\">▲</span>"
-down_arrow <- "<span style=\"color:red\">▼</span>"
-
-# Create a gt table based on a preprocessed `sp500`
-sp500 %>%
- dplyr::filter(date >= start_date & date <= end_date) %>%
- dplyr::select(-adj_close) %>%
- dplyr::mutate(date = as.character(date)) %>%
- gt() %>%
- tab_header(
- title = "S&P 500",
- subtitle = glue::glue("{start_date} to {end_date}")
- ) %>%
- fmt_date(
- columns = vars(date),
- date_style = 7
- ) %>%
- fmt_currency(
- columns = vars(open, high, low, close),
- currency = "USD"
- ) %>%
- fmt_number(
- columns = vars(volume),
- scale_by = 1 / 1E9,
- pattern = "{x}B"
- ) %>%
- text_transform(
- locations = cells_data(
- columns = "close",
- rows = close > open),
- fn = function(x) paste(x, up_arrow)
- ) %>%
- text_transform(
- locations = cells_data(
- columns = "close",
- rows = close < open),
- fn = function(x) paste(x, down_arrow)
- ) %>%
- cols_label(
- date = "Date", open = "Open", high = "High",
- low = "Low", close = "Close", volume = "Volume"
- )
S&P 500 | -|||||
---|---|---|---|---|---|
2010-06-02 to 2010-06-15 | -|||||
Date | -Open | -High | -Low | -Close | -Volume | -
15 Jun 2010 | -$1,091.21 | -$1,115.59 | -$1,091.21 | -$1,115.23 ā² - | -4.64B | -
14 Jun 2010 | -$1,095.00 | -$1,105.91 | -$1,089.03 | -$1,089.63 ā¼ - | -4.43B | -
11 Jun 2010 | -$1,082.65 | -$1,092.25 | -$1,077.12 | -$1,091.60 ā² - | -4.06B | -
10 Jun 2010 | -$1,058.77 | -$1,087.85 | -$1,058.77 | -$1,086.84 ā² - | -5.14B | -
9 Jun 2010 | -$1,062.75 | -$1,077.74 | -$1,052.25 | -$1,055.69 ā¼ - | -5.98B | -
8 Jun 2010 | -$1,050.81 | -$1,063.15 | -$1,042.17 | -$1,062.00 ā² - | -6.19B | -
7 Jun 2010 | -$1,065.84 | -$1,071.36 | -$1,049.86 | -$1,050.47 ā¼ - | -5.47B | -
4 Jun 2010 | -$1,098.43 | -$1,098.43 | -$1,060.50 | -$1,064.88 ā¼ - | -6.18B | -
3 Jun 2010 | -$1,098.82 | -$1,105.67 | -$1,091.81 | -$1,102.83 ā² - | -5.00B | -
2 Jun 2010 | -$1,073.01 | -$1,098.56 | -$1,072.03 | -$1,098.38 ā² - | -5.03B | -
pizzaplace
-The pizzaplace
dataset is unusual to say the least. It brings up more questions than answers. Why is it that the āThe Greekā pizza (the_greek
) comes in XL
and XXL
sizes whilst (almost) all the other pizzas adhere to the S
-M
-L
paradigm? Why is the āBrie Carreā pizza (brie_carre
) only small? Also, is any of this real, and, what is the nature of reality? (All of these questions are quite complicatedāwhile I can doubt the existence of the material world, I cannot doubt the existence of myself as someone thinking about all the delicious pizzas on offer at pizzaplace
.)
We have the 2015 sales from the pizzaplace, where each row is a pizza sold. There are 32 different types of pizza in 4 different categories: classic
, chicken
, supreme
, and veggie
. It was a great year of sales, personal problems notwithstanding. A kitchen fire in late September did not help with the morale situation. Nevertheless, $817,860 in sales for the year! That was indeed something to be cheerful about.
Letās learn more about how this fascinating dataset is structured:
- -Column | -Type | -Description | -
---|---|---|
id | -chr | -The ID for the order, which consists of one or more pizzas at a given `date` and `time` | -
date | -chr | -A character representation of the order `date`, expressed in the ISO 8601 date format (YYYY-MM-DD) | -
time | -chr | -A character representation of the order time, expressed as a 24-hour time the ISO 8601 extended time format (hh:mm:ss) | -
name | -chr | -The short name for the pizza | -
size | -chr | -The size of the pizza, which can either be S, M, L, XL (rare!), or XXL (even rarer!); most pizzas are available in the S, M, and L sizes but exceptions apply | -
type | -chr | -The category or type of pizza, which can either be `classic`, `chicken`, `supreme`, or `veggie` | -
price | -dbl | -The price of the pizza and the amount that it sold for (in USD) | -
pizzaplace
ExampleLetās make a reporting table from the pizzaplace
dataset with these requirements:
size
of pizza from each category (type
)size
-type
(size
provides the row labels and type
forms the row groups)sold
column to use commas and no decimal placesincome
) to be in USD
currency# Create a gt table based on a preprocessed `pizzaplace`
-pizzaplace %>%
- dplyr::group_by(type, size) %>%
- dplyr::summarize(
- sold = n(),
- income = sum(price)
- ) %>%
- gt(rowname_col = "size") %>%
- tab_header(title = "Pizzas Sold in 2015") %>%
- fmt_number(
- columns = vars(sold),
- decimals = 0,
- use_seps = TRUE
- ) %>%
- fmt_currency(
- columns = vars(income),
- currency = "USD"
- ) %>%
- summary_rows(
- groups = TRUE,
- columns = vars(sold),
- fns = list(TOTAL = "sum"),
- formatter = fmt_number,
- decimals = 0,
- use_seps = TRUE
- ) %>%
- summary_rows(
- groups = TRUE,
- columns = "income",
- fns = list(TOTAL = "sum"),
- formatter = fmt_currency,
- currency = "USD"
- ) %>%
- tab_options(
- summary_row.background.color = "#ACEACE",
- stub_group.background.color = "#FFEFDB"
- )
Pizzas Sold in 2015 | -||
---|---|---|
- | ||
- | sold | -income | -
chicken | -||
L | -4,932 | -$102,339.00 | -
M | -3,894 | -$65,224.50 | -
S | -2,224 | -$28,356.00 | -
TOTAL | -11,050 | -$195,919.50 | -
classic | -||
L | -4,057 | -$74,518.50 | -
M | -4,112 | -$60,581.75 | -
S | -6,139 | -$69,870.25 | -
XL | -552 | -$14,076.00 | -
XXL | -28 | -$1,006.60 | -
TOTAL | -14,888 | -$220,053.10 | -
supreme | -||
L | -4,564 | -$94,258.50 | -
M | -4,046 | -$66,475.00 | -
S | -3,377 | -$47,463.50 | -
TOTAL | -11,987 | -$208,197.00 | -
veggie | -||
L | -5,403 | -$104,202.70 | -
M | -3,583 | -$57,101.00 | -
S | -2,663 | -$32,386.75 | -
TOTAL | -11,649 | -$193,690.45 | -
exibble
-The example tibble thatās useful for gt is called exibble
. Itās 8 rows, has clear ordering of data, and the columns contain data that can be tested with the various gt formatter functions (fmt*()
). Here is a table describing the columns of exibble
:
Column | -Type | -Description | -
---|---|---|
num | -dbl | -A numeric column ordered with increasingly larger values | -
char | -chr | -A character column composed of names of fruits from a to h | -
fctr | -fct | -A factor column with numbers from 1 to 8, written out | -
date, time, datetime | -chr | -Character columns with dates, times, and datetimes | -
currency | -dbl | -A numeric column that is useful for testing currency-based formatting | -
row | -chr | -A character column in the format `row_X` which can be useful for testing with row label in a table stub | -
group | -chr | -A character column with four `grp_a` values and four `grp_b` values which can be useful for testing tables that contain row groups | -
exibble
ExampleLetās test as many formatter functions as possible with exibble
while also using row labels and row groups (furnished by the row
and group
columns). Weāll format num
to display numbers with 2 decimal places. The dates in date
will be formatted with date_style
6
(the m_day_year
style, use info_date_style()
to learn about all of them). The 24-h time values in time
will use time_style
4
(hm_p
, more info at info_time_style()
). Datetimes as in datetime
column can be formatted with the fmt_datetime()
function (which uses the date_style
and time_style
arguments). The column currency
will be formatted as a currency with fmt_currency
and weāll consider these values to be euros (currency = "EUR"
).
# Create a gt table based on `exibble`
-exibble %>%
- gt(
- rowname_col = "row",
- groupname_col = "group"
- ) %>%
- fmt_number(
- columns = vars(num),
- decimals = 2) %>%
- fmt_date(
- columns = vars(date),
- date_style = 6
- ) %>%
- fmt_time(
- columns = vars(time),
- time_style = 4
- ) %>%
- fmt_datetime(
- columns = vars(datetime),
- date_style = 6,
- time_style = 4
- ) %>%
- fmt_currency(
- columns = vars(currency),
- currency = "EUR"
- ) %>%
- tab_options(
- column_labels.font.size = "small",
- table.font.size = "small",
- stub_group.font.size = "small",
- row.padding = px(3)
- )
- | num | -char | -fctr | -date | -time | -datetime | -currency | -
---|---|---|---|---|---|---|---|
grp_a | -|||||||
row_1 | -0.11 | -apricot | -one | -Jan 15, 2015 | -1:35 PM | -Jan 1, 2018 2:22 AM | -ā¬49.95 | -
row_2 | -2.22 | -banana | -two | -Feb 15, 2015 | -2:40 PM | -Feb 2, 2018 2:33 PM | -ā¬17.95 | -
row_3 | -33.33 | -coconut | -three | -Mar 15, 2015 | -3:45 PM | -Mar 3, 2018 3:44 AM | -ā¬1.39 | -
row_4 | -444.40 | -durian | -four | -Apr 15, 2015 | -4:50 PM | -Apr 4, 2018 3:55 PM | -ā¬65,100.00 | -
grp_b | -|||||||
row_5 | -5,550.00 | -NA | -five | -May 15, 2015 | -5:55 PM | -May 5, 2018 4:00 AM | -ā¬1,325.81 | -
row_6 | -NA | -fig | -six | -Jun 15, 2015 | -NA | -Jun 6, 2018 4:11 PM | -ā¬13.26 | -
row_7 | -777,000.00 | -grapefruit | -seven | -NA | -7:10 PM | -Jul 7, 2018 5:22 AM | -NA | -
row_8 | -8,880,000.00 | -honeydew | -eight | -Aug 15, 2015 | -8:20 PM | -NA | -ā¬0.44 | -
vignettes/intro-creating-gt-tables.Rmd
- intro-creating-gt-tables.Rmd
The gt package is all about making it simple to produce nice-looking display tables. Display tables? Well yes, we are trying to distinguish between data tables (e.g., tibbles, data.frame
s, etc.) and those tables youād find in a web page, a journal article, or in a magazine. Such tables can likewise be called presentation tables, summary tables, or just tables really. Here are some examples, ripped straight from the web:
We can think of display tables as output only, where weād not want to use them as input ever again. Other features include annotations, table element styling, and text transformations that serve to communicate the subject matter more clearly.
-Letās use a less common dataset that is available in the R datasets package: islands
. Itās actually not a data frame but a named vector. Thatās okay though, we can use use dplyr and prepare a tibble from it:
# Take the `islands` dataset and use some
-# dplyr functionality to obtain the ten
-# biggest islands in the world
-islands_tbl <-
- dplyr::data_frame(
- name = names(islands),
- size = islands
- ) %>%
- dplyr::arrange(desc(size)) %>%
- dplyr::slice(1:10)
-#> Warning: `data_frame()` is deprecated, use `tibble()`.
-#> This warning is displayed once per session.
-
-# Display the table
-islands_tbl
-#> # A tibble: 10 x 2
-#> name size
-#> <chr> <dbl>
-#> 1 Asia 16988
-#> 2 Africa 11506
-#> 3 North America 9390
-#> 4 South America 6795
-#> 5 Antarctica 5500
-#> 6 Europe 3745
-#> 7 Australia 2968
-#> 8 Greenland 840
-#> 9 New Guinea 306
-#> 10 Borneo 280
Given that islands_tbl
is a tibble, we now have a suitable input for gt.
The main entry point into the gt API is the gt()
function. If we pass islands_tbl
to the function gt()
, weāll get a gt Table as output. As an aside, we could have easily used a data frame instead as valid Table Data for gt.
# Create a display table showing ten of
-# the largest islands in the world
-gt_tbl <- gt(data = islands_tbl)
-
-# Show the gt Table
-gt_tbl
name | -size | -
---|---|
Asia | -16988 | -
Africa | -11506 | -
North America | -9390 | -
South America | -6795 | -
Antarctica | -5500 | -
Europe | -3745 | -
Australia | -2968 | -
Greenland | -840 | -
New Guinea | -306 | -
Borneo | -280 | -
That doesnāt look too bad. Sure, itās basic but we really didnāt really ask for much. We did receive a proper table with column labels and the data. Also, that default striping is a nice touch. Oftentimes however, youāll want a bit more: a Table header, a Stub, and sometimes footnotes and source notes in the Table Footer part.
-The gt package makes it relatively easy to add parts so that the resulting gt Table better conveys the information you want to present. These table parts work well together and there the possible variations in arrangement can handle most tabular presentation needs. The previous gt Table demonstrated had only two parts, the Column Labels and the Table Body. The next few examples will show all of the other table parts that are available.
-This is the way the main parts of a table (and their subparts) fit together:
-
-
The parts (roughly from top to bottom) are:
-The way that we add parts like the Table Header and footnotes in the Table Footer is to use the tab_*()
family of functions. A Table Header is easy to add so letās see how the previous table looks with a title and a subtitle. We can add this part using the tab_header()
function:
# Make a display table with the `islands_tbl`
-# table; put a heading just above the column labels
-gt_tbl <-
- gt_tbl %>%
- tab_header(
- title = "Large Landmasses of the World",
- subtitle = "The top ten largest are presented"
- )
-
-# Show the gt Table
-gt_tbl
Large Landmasses of the World | -|
---|---|
The top ten largest are presented | -|
name | -size | -
Asia | -16988 | -
Africa | -11506 | -
North America | -9390 | -
South America | -6795 | -
Antarctica | -5500 | -
Europe | -3745 | -
Australia | -2968 | -
Greenland | -840 | -
New Guinea | -306 | -
Borneo | -280 | -
The Header table part provides an opportunity to describe the data thatās presented. The subtitle
, which functions as a subtitle, is an optional part of the Header. We may also style the title
and subtitle
using Markdown! We do this by wrapping the values passed to title
or subtitle
with the md()
function. Here is an example with the table data truncated for brevity:
# Use markdown for the heading's `title` and `subtitle` to
-# add bold and italicized characters
-gt(islands_tbl[1:2,]) %>%
- tab_header(
- title = md("**Large Landmasses of the World**"),
- subtitle = md("The *top two* largest are presented")
- )
Large Landmasses of the World | -|
---|---|
The top two largest are presented | -|
name | -size | -
Asia | -16988 | -
Africa | -11506 | -
A source note can be added to the tableās footer through use of the tab_source_note()
function. It works in the same way as tab_header()
(it also allows for Markdown inputs) except it can be called multiple timesāeach invocation results in the addition of a source note.
# Display the `islands_tbl` data with a heading and
-# two source notes
-gt_tbl <-
- gt_tbl %>%
- tab_source_note(
- source_note = "Source: The World Almanac and Book of Facts, 1975, page 406."
- ) %>%
- tab_source_note(
- source_note = md("Reference: McNeil, D. R. (1977) *Interactive Data Analysis*. Wiley.")
- )
-
-# Show the gt Table
-gt_tbl
Large Landmasses of the World | -||
---|---|---|
The top ten largest are presented | -||
name | -size | -|
Asia | -16988 | -|
Africa | -11506 | -|
North America | -9390 | -|
South America | -6795 | -|
Antarctica | -5500 | -|
Europe | -3745 | -|
Australia | -2968 | -|
Greenland | -840 | -|
New Guinea | -306 | -|
Borneo | -280 | -|
Source: The World Almanac and Book of Facts, 1975, page 406. | -||
Reference: McNeil, D. R. (1977) Interactive Data Analysis. Wiley. | -
Footnotes live inside the Footer part and their reference glyphs are attached to cell data. Footnotes are added with the tab_footnote()
function. The helper function cells_data()
can be used with the location
argument to specify which data cells should be the target of the footnote. The cells_data()
helper has the two arguments columns
and rows
. For each of these, we can supply (1) a vector of colnames or rownames, (2) a vector of column/row indices, (3) bare column names wrapped in vars()
or row labels within c()
, or (4) a select helper function (starts_with()
, ends_with()
, contains()
, matches()
, one_of()
, and everything()
). For rows
specifically, we can use a conditional statement with column names as variables (e.g., size > 15000
).
Here is a simple example on how a footnotes can be added to a table cell. Letās add a footnote that references the North America
and South America
cells in the name
column:
# Add footnotes (the same text) to two different
-# cell; data cells are targeted with `data_cells()`
-gt_tbl <-
- gt_tbl %>%
- tab_footnote(
- footnote = "The Americas.",
- locations = cells_data(
- columns = vars(name),
- rows = 3:4)
- )
-
-# Show the gt Table
-gt_tbl
Large Landmasses of the World | -||
---|---|---|
The top ten largest are presented | -||
name | -size | -|
Asia | -16988 | -|
Africa | -11506 | -|
North America1 - | -9390 | -|
South America1 - | -6795 | -|
Antarctica | -5500 | -|
Europe | -3745 | -|
Australia | -2968 | -|
Greenland | -840 | -|
New Guinea | -306 | -|
Borneo | -280 | -|
Source: The World Almanac and Book of Facts, 1975, page 406. | -||
Reference: McNeil, D. R. (1977) Interactive Data Analysis. Wiley. | -||
-1 The Americas. | -
Here is a slightly more complex example of adding footnotes that use expressions in rows
to help target cells in a column by the underlying data in islands_tbl
. First, a set of dplyr statements obtains the name of the āislandā by largest landmass. This is assigned to the largest
object and is used in the first tab_footnote()
call that targets the cell in the size
column that is next to a name
value that is stored in largest
(āAsiaā). The second tab_footnote()
is similar except we are supplying a conditional statement that gets the lowest population.
# Determine the row that contains the
-# largest landmass ('Asia')
-largest <-
- islands_tbl %>%
- arrange(desc(size)) %>%
- slice(1) %>%
- pull(name)
-
-# Create two additional footnotes, using the
-# `columns` and `where` arguments of `data_cells()`
-gt_tbl <-
- gt_tbl %>%
- tab_footnote(
- footnote = md("The **largest** by area."),
- locations = cells_data(
- columns = vars(size),
- rows = name == largest)
- ) %>%
- tab_footnote(
- footnote = "The lowest by population.",
- locations = cells_data(
- columns = vars(size),
- rows = size == min(size))
- )
-
-# Show the gt Table
-gt_tbl
Large Landmasses of the World | -||
---|---|---|
The top ten largest are presented | -||
name | -size | -|
Asia | -169881 - | -|
Africa | -11506 | -|
North America2 - | -9390 | -|
South America2 - | -6795 | -|
Antarctica | -5500 | -|
Europe | -3745 | -|
Australia | -2968 | -|
Greenland | -840 | -|
New Guinea | -306 | -|
Borneo | -2803 - | -|
Source: The World Almanac and Book of Facts, 1975, page 406. | -||
Reference: McNeil, D. R. (1977) Interactive Data Analysis. Wiley. | -||
-1 The largest by area. 2 The Americas. 3 The lowest by population. |
-
We were able to supply the reference locations in the table by using the cells_data()
helper function and supplying the necessary targeting through the columns
and rows
arguments. Other cells_*()
functions have similar interfaces and they allow us to target cells in different parts of the table.
The Stub is the area to the left in a table that contains row labels, and may contain row group labels, and summary labels. Those subparts can be grouped in a sequence of row groups. The Stub Head provides a location for a label that describes the Stub. The Stub is optional since there are cases where a Stub wouldnāt be useful (e.g., the display tables presented above were just fine without a Stub).
-An easy way to generate a Stub part is by specifying a stub column in the gt()
function with the rowname_col
argument. Alternatively, we can have an input dataset with a column named rowname
āthis magic column will signal to gt that that column should be used as the stub, making row labels. Letās add a stub with our islands_tbl
dataset by modifying the call to gt()
:
# Create a gt table showing ten of the
-# largest islands in the world; this
-# time with a stub
-gt_tbl <-
- islands_tbl %>%
- gt(rowname_col = "name")
-
-# Show the gt Table
-gt_tbl
- | size | -
---|---|
Asia | -16988 | -
Africa | -11506 | -
North America | -9390 | -
South America | -6795 | -
Antarctica | -5500 | -
Europe | -3745 | -
Australia | -2968 | -
Greenland | -840 | -
New Guinea | -306 | -
Borneo | -280 | -
Notice that the landmass names are off the the left in an unstriped area? Thatās the stub. We can apply whatās known as a stubhead label. This label can be added with the tab_stubhead_label()
function:
# Generate a simple table with a stub
-# and add a stubhead label
-gt_tbl <-
- gt_tbl %>%
- tab_stubhead_label(label = "landmass")
-
-# Show the gt Table
-gt_tbl
landmass | -size | -
---|---|
Asia | -16988 | -
Africa | -11506 | -
North America | -9390 | -
South America | -6795 | -
Antarctica | -5500 | -
Europe | -3745 | -
Australia | -2968 | -
Greenland | -840 | -
New Guinea | -306 | -
Borneo | -280 | -
A very important thing to note here is that the table now has one column. Before, when there was no stub, two columns were present (with column labels name
and size
) but now column number 1
(the only column) is size
.
To apply our table parts as before (up to and including the footnotes) we use the following statements:
-# Display the `islands_tbl` data with a stub,
-# a heading, source notes, and footnotes
-gt_tbl <-
- gt_tbl %>%
- tab_header(
- title = "Large Landmasses of the World",
- subtitle = "The top ten largest are presented"
- ) %>%
- tab_source_note(
- source_note = "Source: The World Almanac and Book of Facts, 1975, page 406."
- ) %>%
- tab_source_note(
- source_note = md("Reference: McNeil, D. R. (1977) *Interactive Data Analysis*. Wiley.")
- ) %>%
- tab_footnote(
- footnote = md("The **largest** by area."),
- locations = cells_data(
- columns = vars(size),
- rows = largest)
- ) %>%
- tab_footnote(
- footnote = "The lowest by population.",
- locations = cells_data(
- columns = vars(size),
- rows = contains("arc"))
- )
-
-# Show the gt Table
-gt_tbl
Large Landmasses of the World | -||
---|---|---|
The top ten largest are presented | -||
landmass | -size | -|
Asia | -169881 - | -|
Africa | -11506 | -|
North America | -9390 | -|
South America | -6795 | -|
Antarctica | -55002 - | -|
Europe | -3745 | -|
Australia | -2968 | -|
Greenland | -840 | -|
New Guinea | -306 | -|
Borneo | -280 | -|
Source: The World Almanac and Book of Facts, 1975, page 406. | -||
Reference: McNeil, D. R. (1977) Interactive Data Analysis. Wiley. | -||
-1 The largest by area. 2 The lowest by population. |
-
Letās incorporate row groups into the display table. This divides rows into groups, creating row groups, and results in a display of a row group labels right above the each group. This can be easily done with a table containing row labels. We can make a new row group with each call of the tab_row_group()
function. The inputs are group names in the group
argument, and row references in the rows
argument. We can use any of the strategies to reference rows as we did we footnotes (e.g., vectors of names/indices, select helpers, etc.).
Here we will create three row groups (with row group labels continent
, country
, and subregion
) to have a grouping of rows.
# Create three row groups with the
-# `tab_row_group()` function
-gt_tbl <-
- gt_tbl %>%
- tab_row_group(
- group = "continent",
- rows = 1:6
- ) %>%
- tab_row_group(
- group = "country",
- rows = c("Australia", "Greenland")
- ) %>%
- tab_row_group(
- group = "subregion",
- rows = c("New Guinea", "Borneo")
- )
-
-# Show the gt Table
-gt_tbl
-#> Warning in min(rows_matched): no non-missing arguments to min; returning
-#> Inf
-#> Warning in max(rows_matched): no non-missing arguments to max; returning -
-#> Inf
Large Landmasses of the World | -||
---|---|---|
The top ten largest are presented | -||
landmass | -size | -|
continent | -||
Asia | -169881 - | -|
Africa | -11506 | -|
North America | -9390 | -|
South America | -6795 | -|
Antarctica | -55002 - | -|
Europe | -3745 | -|
country | -||
Australia | -2968 | -|
Greenland | -840 | -|
subregion | -||
New Guinea | -306 | -|
Borneo | -280 | -|
Source: The World Almanac and Book of Facts, 1975, page 406. | -||
Reference: McNeil, D. R. (1977) Interactive Data Analysis. Wiley. | -||
-1 The largest by area. 2 The lowest by population. |
-
Three row groups have been made since there are three unique categories under groupname
. Across the top of each row group is the row group label contained in a separate row (these cut across the field and they contain nothing but the row group label). A rearrangement of rows is carried out to ensure each of the rows is collected within the appropriate row groups.
Having groups of rows in row groups is a great way to present information. Including data summaries particular to each group is a natural extension of this idea. This process of adding summary rows with summary labels is covered in a separate article (Creating Summary Lines).
-Another way to make row groups is to have the magic column groupname
present in the input data table. For our above example with islands_tbl
, a groupname
column with the categories continent
, country
, and subregion
in the appropriate rows would produce row groups automatically (i.e., there would be no need to use the tab_row_group()
statements). This strategy of supplying group names in a groupname
column name can sometimes be advantageous since we can rely on functions such as those available in dplyr to generate the categories (e.g., using case_when()
or if_else()
).
The tableās Column Labels part contains, at a minimum, columns and their column labels. The last example had a single column: size
. Just as in the Stub, we can create groupings called spanner columns that encompass one or more columns.
To better demonstrate how Column Labels work and are displayed, letās use an input data table with more columns. In this case, that input table will be airquality
. It has the following columns:
Ozone
: mean ground-level ozone in parts per billion by volume (ppbV), measured between 13:00 and 15:00Solar.R
: solar radiation in Langley units (cal/m2), measured between 08:00 and noonWind
: mean wind speed in miles per hour (mph)Temp
: maximum daily air temperature in degrees Fahrenheit (Ā°F)Month
, Day
: the numeric month and day of month for the recordWe know that all measurements took place in 1973, so a year
column will be added to the dataset before it is passed to gt()
.
Letās organize the time information under a Time
spanner column label, and put the other columns under a Measurement
spanner column label. We can do this with the tab_spanner()
function.
# Modify the `airquality` dataset by adding the year
-# of the measurements (1973) and limiting to 10 rows
-airquality_m <-
- airquality %>%
- mutate(Year = 1973L) %>%
- slice(1:10)
-
-# Create a display table using the `airquality`
-# dataset; arrange columns into groups
-gt_tbl <-
- gt(data = airquality_m) %>%
- tab_header(
- title = "New York Air Quality Measurements",
- subtitle = "Daily measurements in New York City (May 1-10, 1973)"
- ) %>%
- tab_spanner(
- label = "Time",
- columns = vars(Year, Month, Day)
- ) %>%
- tab_spanner(
- label = "Measurement",
- columns = vars(Ozone, Solar.R, Wind, Temp)
- )
-
-# Show the gt Table
-gt_tbl
New York Air Quality Measurements | -||||||
---|---|---|---|---|---|---|
Daily measurements in New York City (May 1-10, 1973) | -||||||
Measurement | -Time | -|||||
Ozone | -Solar.R | -Wind | -Temp | -Month | -Day | -Year | -
41 | -190 | -7.4 | -67 | -5 | -1 | -1973 | -
36 | -118 | -8.0 | -72 | -5 | -2 | -1973 | -
12 | -149 | -12.6 | -74 | -5 | -3 | -1973 | -
18 | -313 | -11.5 | -62 | -5 | -4 | -1973 | -
NA | -NA | -14.3 | -56 | -5 | -5 | -1973 | -
28 | -NA | -14.9 | -66 | -5 | -6 | -1973 | -
23 | -299 | -8.6 | -65 | -5 | -7 | -1973 | -
19 | -99 | -13.8 | -59 | -5 | -8 | -1973 | -
8 | -19 | -20.1 | -61 | -5 | -9 | -1973 | -
NA | -194 | -8.6 | -69 | -5 | -10 | -1973 | -
We can do two more things to make this presentable:
-Time
columns to the beginning of the series (using cols_move_to_start()
)cols_label()
)Letās do both of these things in the next example.
-# Move the time-based columns to the start of
-# the column series; modify the column labels of
-# the measurement-based columns
-gt_tbl <-
- gt_tbl %>%
- cols_move_to_start(
- columns = vars(Year, Month, Day)
- ) %>%
- cols_label(
- Ozone = html("Ozone,<br>ppbV"),
- Solar.R = html("Solar R.,<br>cal/m<sup>2</sup>"),
- Wind = html("Wind,<br>mph"),
- Temp = html("Temp,<br>°F")
- )
-
-# Show the gt Table
-gt_tbl
New York Air Quality Measurements | -||||||
---|---|---|---|---|---|---|
Daily measurements in New York City (May 1-10, 1973) | -||||||
Time | -Measurement | -|||||
Year | -Month | -Day | -Ozone, ppbV |
-Solar R., cal/m2 - |
-Wind, mph |
-Temp, Ā°F |
-
1973 | -5 | -1 | -41 | -190 | -7.4 | -67 | -
1973 | -5 | -2 | -36 | -118 | -8.0 | -72 | -
1973 | -5 | -3 | -12 | -149 | -12.6 | -74 | -
1973 | -5 | -4 | -18 | -313 | -11.5 | -62 | -
1973 | -5 | -5 | -NA | -NA | -14.3 | -56 | -
1973 | -5 | -6 | -28 | -NA | -14.9 | -66 | -
1973 | -5 | -7 | -23 | -299 | -8.6 | -65 | -
1973 | -5 | -8 | -19 | -99 | -13.8 | -59 | -
1973 | -5 | -9 | -8 | -19 | -20.1 | -61 | -
1973 | -5 | -10 | -NA | -194 | -8.6 | -69 | -
Note that even though columns were moved using cols_move_to_start()
, the spanner column labels still spanned above the correct column labels. There are a number of functions that gt provides to move columns, including cols_move()
, cols_move_to_end()
; thereās even a function to hide columns: cols_hide()
.
Multiple columns can be renamed in a single use of cols_label()
. Further to this, the helper functions md()
and html()
can be used to create column labels with additional styling. In the above example, we provided column labels as HTML so that we can insert linebreaks with <br>
, insert a superscripted 2
(with <sup>2</sup>
), and insert a degree symbol as an HTML entity (°
).
With the gt package, anyone can make wonderful-looking tables using the R programming language. The gt philosophy: we can construct a wide variety of useful tables with a cohesive set of table parts. These include the table header, the stub, the stub head, the column labels, the table body, and the table footer.
-
-
It all begins with preprocessed table data (be it a tibble or a data frame). You decide how to compose your gt table with the elements you need for the task at hand. Output can either be in the form of HTML, LaTeX, or RTF. All work beautifully inside R Markdown documents.
-
-
The gt API is designed to be both straightforward yet powerful. The emphasis is on simple functions for the everyday display table needs. Here is a brief example of how to use gt to create an HTML gt Table from the included sp500
dataset:
library(gt)
-library(tidyverse)
-library(glue)
-
-# Define the start and end dates for the data range
-start_date <- "2010-06-07"
-end_date <- "2010-06-14"
-
-# Create a gt table based on preprocessed
-# `sp500` table data
-sp500 %>%
- dplyr::filter(date >= start_date & date <= end_date) %>%
- dplyr::select(-adj_close) %>%
- dplyr::mutate(date = as.character(date)) %>%
- gt() %>%
- tab_header(
- title = "S&P 500",
- subtitle = glue::glue("{start_date} to {end_date}")
- ) %>%
- fmt_date(
- columns = vars(date),
- date_style = 3
- ) %>%
- fmt_currency(
- columns = vars(open, high, low, close),
- currency = "USD"
- ) %>%
- fmt_number(
- columns = vars(volume),
- scale_by = 1 / 1E9,
- pattern = "{x}B"
- )
-
There are six datasets included in gt: countrypops
, sza
, gtcars
, sp500
, pizzaplace
, and exibble
. All of them are useful for experimenting with the API.
-
Beyond this simple example, there are many functions available in gt that make it possible to create highly customized tables.
-
-
Want to try this out? First and foremost, the gt package is used in an R environment, so, if you donāt have an R installation, it can be obtained from the Comprehensive R Archive Network (CRAN). For the best experience in working with R, use the RStudio Desktop IDE.
-You can install the development version of gt from GitHub. Use the following in the R console to install gt.
- -If you encounter a bug, have usage questions, or want to share ideas to make this package better, feel free to file an issue.
-NEWS.md
- This function can brighten or darken a palette of colors by an arbitrary -number of steps, which is defined by a real number between -2.0 and 2.0. The -transformation of a palette by a fixed step in this function will tend to -apply greater darkening or lightening for those colors in the midrange -compared to any very dark or very light colors in the input palette.
- -adjust_luminance(colors, steps)- -
colors | -a vector of colors that will undergo an adjustment in
-luminance. Each color value provided must either be a color name (in the
-set of colors provided by |
-
---|---|
steps | -a positive or negative factor by which the luminance will be
-adjusted. Must be a number between |
-
This function can be useful when combined with the data_color()
-function's palette
argument, which can use a vector of colors or any
-of the col_*
functions from the scales package (all of which
-have a palette
argument).
-# Get a palette of 8 pastel colors from -# the RColorBrewer package -pal <- RColorBrewer::brewer.pal(8, "Pastel2") - -# Create lighter and darker variants -# of the base palette (one step lower, one -# step higher) -pal_darker <- pal %>% adjust_luminance(-1.0) -pal_lighter <- pal %>% adjust_luminance(+1.0) - -# Create a tibble and make a gt table -# from it; color each column in order of -# increasingly darker palettes (with -# `data_color()`) -tab_1 <- - dplyr::tibble(a = 1:8, b = 1:8, c = 1:8) %>% - gt() %>% - data_color( - columns = vars(a), - colors = scales::col_numeric( - palette = pal_lighter, - domain = c(1, 8) - ) - ) %>% - data_color( - columns = vars(b), - colors = scales::col_numeric( - palette = pal, - domain = c(1, 8) - ) - ) %>% - data_color( - columns = vars(c), - colors = scales::col_numeric( - palette = pal_darker, - domain = c(1, 8) - ) - )
Get the LaTeX content from a gt_tbl
object as a knit_asis
-object. This object contains the LaTeX code and attributes that serve as
-LaTeX dependencies (i.e., the LaTeX packages required for the table). Using
-as.character()
on the created object will result in a single-element
-vector containing the LaTeX code.
as_latex(data)- -
data | -a table object that is created using the |
-
---|
Other table export functions: as_raw_html
,
- as_rtf
, extract_summary
-# Use `gtcars` to create a gt table; -# add a header and then export as -# an object with LaTeX code -tab_latex <- - gtcars %>% - dplyr::select(mfr, model, msrp) %>% - dplyr::slice(1:5) %>% - gt() %>% - tab_header( - title = md("Data listing from **gtcars**"), - subtitle = md("`gtcars` is an R dataset") - ) %>% - as_latex() - -# `tab_latex` is a `knit_asis` object, -# which makes it easy to include in -# R Markdown documents that are knit to -# PDF; we can use `as.character()` to -# get just the LaTeX code as a single- -# element vector -tab_latex %>% - as.character() %>% - cat()#> \captionsetup[table]{labelformat=empty,skip=1pt} -#> \begin{longtable}{llr} -#> \caption*{ -#> \large Data listing from \textbf{gtcars}\\ -#> \small \texttt{gtcars} is an R dataset\\ -#> } \\ -#> \toprule -#> mfr & model & msrp \\ -#> \midrule -#> Ford & GT & 447000 \\ -#> Ferrari & 458 Speciale & 291744 \\ -#> Ferrari & 458 Spider & 263553 \\ -#> Ferrari & 458 Italia & 233509 \\ -#> Ferrari & 488 GTB & 245400 \\ -#> \bottomrule -#> \end{longtable}-
Get the HTML content from a gt_tbl
object as a single-element
-character vector. By default, the generated HTML will have inlined styles,
-where CSS styles (that were previously contained in CSS rule sets external to
-the <table> element
) are included as style
attributes in the
-HTML table's tags. This option is preferable when using the output HTML table
-in an emailing context.
as_raw_html(data, inline_css = TRUE)- -
data | -a table object that is created using the |
-
---|---|
inline_css | -an option to supply styles to table elements as inlined CSS -styles. |
-
Other table export functions: as_latex
,
- as_rtf
, extract_summary
-# Use `gtcars` to create a gt table; -# add a header and then export as -# HTML code with CSS inlined -tab_html <- - gtcars %>% - dplyr::select(mfr, model, msrp) %>% - dplyr::slice(1:5) %>% - gt() %>% - tab_header( - title = md("Data listing from **gtcars**"), - subtitle = md("`gtcars` is an R dataset") - ) %>% - as_raw_html() - -# `tab_html` is a single-element vector -# containing inlined HTML for the table; -# it has only the `<table>...</table>` part -# so it's not a complete HTML document but -# rather an HTML fragment -tab_html %>% - substr(1, 700) %>% - cat()#> <!--gt table start--> -#> <table style="font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Helvetica Neue', 'Fira Sans', 'Droid Sans', Arial, sans-serif;display:table;border-collapse:collapse;margin-left:auto;margin-right:auto;color:#000000;font-size:16px;background-color:#FFFFFF;width:auto;border-top-style:solid;border-top-width:2px;border-top-color:#A8A8A8;"> -#> <thead> -#> <tr> -#> <th colspan='3' style="background-color:#FFFFFF;border-bottom-color:#FFFFFF;color:#000000;font-size:125%;padding-top:4px;padding-bottom:1px;border-bottom-width:0;text-align:center;font-weight:normal;" >Data listing from <strong>gtcars</strong></th> -#> </tr> -#> <tr> -#> <th colspan='3' style="-
Get the RTF content from a gt_tbl
object as as a single-element
-character vector. This object can be used with writeLines()
to
-generate a valid .rtf file that can be opened by RTF readers.
as_rtf(data)- -
data | -a table object that is created using the |
-
---|
Other table export functions: as_latex
,
- as_raw_html
, extract_summary
-# Use `gtcars` to create a gt table; -# add a header and then export as -# RTF code -tab_rtf <- - gtcars %>% - dplyr::select(mfr, model) %>% - dplyr::slice(1:2) %>% - gt() %>% - tab_header( - title = md("Data listing from **gtcars**"), - subtitle = md("`gtcars` is an R dataset") - ) %>% - as_rtf() - -# `tab_rtf` is a single element character -# vector -tab_rtf %>% cat()#> {\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf400 -#> {\fonttbl\f0\fswiss\fcharset0 Helvetica;} -#> {\colortbl;\red255\green255\blue255; -#> } -#> {\*\expandedcolortbl;;\cssrgb\c0\c0\c0;\cssrgb\c37036\c37036\c37036;\csgray\c0\c0; -#> } -#> \deftab20 -#> \cf0 -#> \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrt\brdrnil \trbrdrl\brdrnil \trbrdrr\brdrnil -#> \clmgf \clvertalb \clshdrawnil \clheight340 \clbrdrt\brdrs\brdrw40\brdrcf3 \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadl100 \clpadr100 \clpadt100 \gaph\cellx935 -#> \clmrg \clvertalb \clshdrawnil \clheight340 \clbrdrt\brdrs\brdrw40\brdrcf3 \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadl100 \clpadr100 \clpadt100 \gaph\cellx1870 -#> \pard\intbl\itap1\pardeftab20\qc\partightenfactor0 -#> \f0\fs36 \expnd0\expndtw0\kerning0 -#> \up0 \nosupersub \ulnone \outl0\strokewidth0 \strokec2 Data listing from **gtcars** -#> \fs24 \kerning1\expnd0\expndtw0 \up0 \nosupersub \ulnone \outl0\strokewidth0 \cell -#> \pard\intbl\itap1\cell -#> \row -#> -#> \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil -#> \clmgf \clvertalc \clshdrawnil \clheight240 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrs\brdrw40\brdrcf3 \clbrdrr\brdrnil \clpadl100 \clpadr100 \clpadb100 \gaph\cellx935 -#> \clmrg \clvertalc \clshdrawnil \clheight240 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrs\brdrw40\brdrcf3 \clbrdrr\brdrnil \clpadl100 \clpadr100 \clpadb100 \gaph\cellx1870 -#> \pard\intbl\itap1\pardeftab20\qc\partightenfactor0 -#> -#> \fs20 \expnd0\expndtw0\kerning0\up0 \nosupersub \ulnone \outl0\strokewidth0 \strokec2 `gtcars` is an R dataset -#> \fs28 \kerning1\expnd0\expndtw0 \up0 \nosupersub \ulnone \outl0\strokewidth0 \cell\pard\intbl\itap1\cell -#> \row\itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil -#> \clvertalc \clshdrawnil \clheight520 \clbrdrt\brdrs\brdrw40\brdrcf3 \clbrdrl\brdrnil \clbrdrb\brdrs\brdrw40\brdrcf3 \clbrdrr\brdrnil \clpadl100 \clpadr100 \gaph\cellx935 -#> \clvertalc \clshdrawnil \clheight520 \clbrdrt\brdrs\brdrw40\brdrcf3 \clbrdrl\brdrnil \clbrdrb\brdrs\brdrw40\brdrcf3 \clbrdrr\brdrnil \clpadl100 \clpadr100 \gaph\cellx1870 -#> \pard\intbl\itap1\pardeftab20\qc\partightenfactor0 -#> \expnd0\expndtw0\kerning0 -#> \up0 \nosupersub \ulnone \outl0\strokewidth0 \strokec2 mfr \kerning1\expnd0\expndtw0 \up0 \nosupersub \ulnone \outl0\strokewidth0 \cell -#> \pard\intbl\itap1\pardeftab20\qc\partightenfactor0 -#> \expnd0\expndtw0\kerning0 -#> \up0 \nosupersub \ulnone \outl0\strokewidth0 \strokec2 model \kerning1\expnd0\expndtw0 \up0 \nosupersub \ulnone \outl0\strokewidth0 \cell -#> \row\itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil -#> \clvertalc \clshdrawnil \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadl100 \clpadr100 \clpadt50 \clpadb50 \gaph\cellx935 -#> \clvertalc \clshdrawnil \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadl100 \clpadr100 \clpadt50 \clpadb50 \gaph\cellx1870 -#> \pard\intbl\itap1\pardeftab20\qc\partightenfactor0 -#> \expnd0\expndtw0\kerning0 -#> \up0 \nosupersub \ulnone \outl0\strokewidth0 \strokec2 Ford \kerning1\expnd0\expndtw0 \up0 \nosupersub \ulnone \outl0\strokewidth0 \cell -#> \pard\intbl\itap1\pardeftab20\qc\partightenfactor0 -#> \expnd0\expndtw0\kerning0 -#> \up0 \nosupersub \ulnone \outl0\strokewidth0 \strokec2 GT \kerning1\expnd0\expndtw0 \up0 \nosupersub \ulnone \outl0\strokewidth0 \cell -#> \row\itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil -#> \clvertalc \clshdrawnil \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrs\brdrw40\brdrcf3 \clbrdrr\brdrnil \clpadl100 \clpadr100 \clpadt50 \clpadb50 \gaph\cellx935 -#> \clvertalc \clshdrawnil \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrs\brdrw40\brdrcf3 \clbrdrr\brdrnil \clpadl100 \clpadr100 \clpadt50 \clpadb50 \gaph\cellx1870 -#> \pard\intbl\itap1\pardeftab20\qc\partightenfactor0 -#> \expnd0\expndtw0\kerning0 -#> \up0 \nosupersub \ulnone \outl0\strokewidth0 \strokec2 Ferrari \kerning1\expnd0\expndtw0 \up0 \nosupersub \ulnone \outl0\strokewidth0 \cell -#> \pard\intbl\itap1\pardeftab20\qc\partightenfactor0 -#> \expnd0\expndtw0\kerning0 -#> \up0 \nosupersub \ulnone \outl0\strokewidth0 \strokec2 458 Speciale \kerning1\expnd0\expndtw0 \up0 \nosupersub \ulnone \outl0\strokewidth0\expnd0\expndtw0\kerning0 -#> \up0 \nosupersub \ulnone \outl0\strokewidth0 \strokec2 \cell \lastrow\row}-
This helper function is to be used with the tab_style()
-function, which itself allows for the setting of custom styles to one or more
-cells. We can also define several styles within a single call of
-cells_styles
and tab_style()
will reliably apply those
-styles to the targeted element.
cells_styles(bkgd_color = NULL, text_color = NULL, text_font = NULL, - text_size = NULL, text_align = NULL, text_style = NULL, - text_weight = NULL, text_stretch = NULL, text_indent = NULL, - text_decorate = NULL, text_transform = NULL)- -
bkgd_color | -the background color of the cell. |
-
---|---|
text_color | -the text color. |
-
text_font | -the font or collection of fonts (subsequent font names are) -used as fallbacks. |
-
text_size | -the size of the font. Can be provided as a number that is
-assumed to represent |
-
text_align | -the text alignment. Can be one of either |
-
text_style | -the text style. Can be one of either |
-
text_weight | -the weight of the font. Can be a text-based keyword such
-as |
-
text_stretch | -allows for text to either be condensed or expanded. We
-can use the following text-based keywords to describe the degree of
-condensation/expansion: |
-
text_indent | -the indentation of the text. |
-
text_decorate | -allows for text decoration effect to be applied. Here,
-we can use |
-
text_transform | -allows for the transformation of text. Options are
- |
-
a character vector containing formatted styles.
- -Other helper functions: escape_latex
,
- gt_latex_dependencies
, html
,
- md
, pct
, px
The individual alignments of columns (which includes the column labels and
-all of their data cells) can be modified. We have the option to align text to
-the left
, the center
, and the right
. In a less explicit
-manner, we can allow gt to automatically choose the alignment of each
-column based on the data type (with the auto
option).
cols_align(data, align = c("auto", "left", "center", "right"), - columns = TRUE)- -
data | -a table object that is created using the |
-
---|---|
align | -the alignment type. This can be any of |
-
columns | -an optional vector of column names for which the alignment
-should be applied. If nothing is supplied, or if |
-
an object of class gt_tbl
.
When you create a gt table object using gt()
, automatic
-alignment of column labels and their data cells is performed. By default,
-left-alignment is applied to columns of class character
, Date
,
-or POSIXct
; center-alignment is for columns of class logical
,
-factor
, or list
; and right-alignment is used for the
-numeric
and integer
columns.
Other column modification functions: cols_hide
,
- cols_label
, cols_merge_range
,
- cols_merge_uncert
,
- cols_merge
, cols_move_to_end
,
- cols_move_to_start
,
- cols_move
, cols_split_delim
-
The cols_hide()
function allows us to hide one or more columns from
-appearing in the final output table. While it's possible and often desirable
-to omit columns from the input table data before introduction to the
-gt()
function, there can be cases where the data in certain
-columns is useful (as a column reference during formatting of other columns)
-but the final display of those columns is not necessary.
cols_hide(data, columns)- -
data | -a table object that is created using the |
-
---|---|
columns | -the column names to hide from the output display table. The -order of the remaining columns will be preserved. Values provided that do -not correspond to column names will be disregarded. |
-
an object of class gt_tbl
.
The hiding of columns is internally a rendering directive, so, all columns
-that are 'hidden' are still accessible and useful in any expression provided
-to a rows
argument. Furthermore, the cols_hide()
function (as
-with many gt functions) can be placed anywhere in a pipeline of
-gt function calls (acting as a promise to hide columns when the timing
-is right). However there's perhaps greater readability when placing this call
-closer to the end of such a pipeline.
Other column modification functions: cols_align
,
- cols_label
, cols_merge_range
,
- cols_merge_uncert
,
- cols_merge
, cols_move_to_end
,
- cols_move_to_start
,
- cols_move
, cols_split_delim
-# Use `countrypops` to create a gt table; -# Hide the columns `country_code_2` and -# `country_code_3` -tab_1 <- - countrypops %>% - dplyr::filter(country_name == "Mongolia") %>% - tail(5) %>% - gt() %>% - cols_hide( - columns = vars( - country_code_2, country_code_3) - ) - -# Use `countrypops` to create a gt table; -# Use the `population` column to provide -# the conditional placement of footnotes, -# then hide that column and one other -tab_2 <- - countrypops %>% - dplyr::filter(country_name == "Mongolia") %>% - tail(5) %>% - gt() %>% - cols_hide( - columns = vars(country_code_3, population) - ) %>% - tab_footnote( - footnote = "Population above 3,000,000.", - locations = cells_data( - columns = vars(year), - rows = population > 3000000) - )
Column labels can be modified from their default values (the names of the
-columns from the input table data). When you create a gt table object
-using gt()
, column names effectively become the column labels.
-While this serves as a good first approximation, column names aren't often
-appealing as column labels in a gt output table. The
-cols_label()
function provides the flexibility to relabel one or more
-columns and we even have the option to use the md()
or
-html()
helper functions for rendering column labels from
-Markdown or using HTML.
cols_label(data, ..., .list = list2(...))- -
data | -a table object that is created using the |
-
---|---|
... | -one or more named arguments of column names from the input `data`
-table along with their labels for display as the column labels. We can
-optionally wrap the column labels with |
-
.list | -allows for the use of a list as an input alternative to
- |
-
It's important to note that while columns can be freely relabeled, we
-continue to refer to columns by their original column names. Column names in
-a tibble or data frame must be unique whereas column labels in gt
-have no requirement for uniqueness (which is useful for labeling columns as,
-say, measurement units that may be repeated several times---usually under
-different spanner column labels). Thus, we can still easily distinguish
-between columns in other gt function calls (e.g., in all of the
-fmt*()
functions) even though we may lose distinguishability in column
-labels once they have been relabeled.
Other column modification functions: cols_align
,
- cols_hide
, cols_merge_range
,
- cols_merge_uncert
,
- cols_merge
, cols_move_to_end
,
- cols_move_to_start
,
- cols_move
, cols_split_delim
-# Use `countrypops` to create a gt table; -# label all the table's columns to -# present better -tab_1 <- - countrypops %>% - dplyr::select(-contains("code")) %>% - dplyr::filter(country_name == "Mongolia") %>% - tail(5) %>% - gt() %>% - cols_label( - country_name = "Name", - year = "Year", - population = "Population" - ) - -# Use `countrypops` to create a gt table; -# label columns as before but make them -# bold with markdown formatting -tab_2 <- - countrypops %>% - dplyr::select(-contains("code")) %>% - dplyr::filter(country_name == "Mongolia") %>% - tail(5) %>% - gt() %>% - cols_label( - country_name = md("**Name**"), - year = md("**Year**"), - population = md("**Population**") - )
This function takes any two columns and merges them into a single column,
-using a pattern that specifies how the values in the data cells are combined.
-We specify the columns to merge together in the col_1
and col_2
-arguments and the string-combining pattern is specified in pattern
.
-The column that is retained is that of col_1
whereas the column
-specified in col_2
is dropped from the output table.
cols_merge(data, col_1, col_2, pattern = "{1} {2}")- -
data | -a table object that is created using the |
-
---|---|
col_1 | -a retained column that contains values to be merged with those
-in |
-
col_2 | -a column that contains values to be merged with those in
- |
-
pattern | -a formatting pattern that specifies the arrangement of the
- |
-
an object of class gt_tbl
.
There are two other column-merging functions that offer specialized behavior
-that is optimized for common table tasks: cols_merge_range()
-and cols_merge_uncert()
. These functions operate similarly,
-where the second column specified is dropped from the output table. For all
-of the cols_merge*()
functions, column removal occurs late in the
-rendering lifecycle so those secondary columns are still usable as column
-references (e.g., inside expressions provided to `rows` in the fmt*()
-functions).
Other column modification functions: cols_align
,
- cols_hide
, cols_label
,
- cols_merge_range
,
- cols_merge_uncert
,
- cols_move_to_end
,
- cols_move_to_start
,
- cols_move
, cols_split_delim
-# Use `sp500` to create a gt table; -# merge the `open` & `close` columns -# together, and, the `low` & `high` -# columns (putting an em dash between -# both); rename the columns -tab_1 <- - sp500 %>% - dplyr::slice(50:55) %>% - dplyr::select(-volume, -adj_close) %>% - gt() %>% - cols_merge( - col_1 = vars(open), - col_2 = vars(close), - pattern = "{1}—{2}" - ) %>% - cols_merge( - col_1 = vars(low), - col_2 = vars(high), - pattern = "{1}—{2}" - ) %>% - cols_label( - open = "open/close", - low = "low/high" - )
The cols_merge_range()
function is a specialized variant of the
-cols_merge()
function. It operates by taking a two columns that
-constitute a range of values (col_begin
and col_end
) and merges
-them into a single column. What results is a column containing both values
-separated by a long dash (e.g., 12.0 ā 20.0
). The column specified in
-col_end
is dropped from the output table.
cols_merge_range(data, col_begin, col_end)- -
data | -a table object that is created using the |
-
---|---|
col_begin | -a column that contains values for the start of the range. |
-
col_end | -a column that contains values for the end of the range. |
-
an object of class gt_tbl
.
This function could be somewhat replicated using cols_merge()
,
-however, cols_merge_range()
employs the following specialized
-semantics for NA
handling:
NA
s in col_begin
result in missing values for the merged
-column (e.g., NA
+ 20.0
= NA
)
NA
s in col_end
(but not col_begin
) result in
-a display of only the col_begin
values only for the merged column
-(e.g., 12.0
+ NA
= 12.0
)
NA
s both col_begin
and col_end
result in
-missing values for the merged column (e.g., NA
+ NA
=
-NA
)
Any resulting NA
values in the col_begin
column following the
-merge operation can be easily formatted using the fmt_missing()
-function.
This function is part of a set of three column-merging functions. The other
-two are the general cols_merge()
function and the specialized
-cols_merge_uncert()
function. These functions operate
-similarly, where the second column specified is dropped from the output
-table. For all of the cols_merge*()
functions, column removal occurs
-late in the rendering lifecycle so those secondary columns are still usable
-as column references (e.g., inside expressions provided to `rows` in the
-fmt*()
functions).
Other column modification functions: cols_align
,
- cols_hide
, cols_label
,
- cols_merge_uncert
,
- cols_merge
, cols_move_to_end
,
- cols_move_to_start
,
- cols_move
, cols_split_delim
-# Use `gtcars` to create a gt table, -# keeping only the `model`, `mpg_c`, -# and `mpg_h` columns; merge the mpg -# columns together as a single range -# column (which is labeled as MPG, -# in italics) -tab_1 <- - gtcars %>% - dplyr::select(model, starts_with("mpg")) %>% - dplyr::slice(1:8) %>% - gt() %>% - cols_merge_range( - col_begin = vars(mpg_c), - col_end = vars(mpg_h)) %>% - cols_label( - mpg_c = md("*MPG*") - )
R/modify_columns.R
- cols_merge_uncert.Rd
The cols_merge_uncert()
function is a specialized variant of the
-cols_merge()
function. It operates by taking a base value
-column (col_val
) and an uncertainty column (col_uncert
) and
-merges them into a single column. What results is a column with values and
-associated uncertainties (e.g., 12.0 Ā± 0.1
), and, the column specified
-in col_uncert
is dropped from the output table.
cols_merge_uncert(data, col_val, col_uncert)- -
data | -a table object that is created using the |
-
---|---|
col_val | -a single column name that contains the base values. |
-
col_uncert | -a single column name that contains the uncertainty values. |
-
an object of class gt_tbl
.
This function could be somewhat replicated using cols_merge()
,
-however, cols_merge_uncert()
employs the following specialized
-semantics for NA
handling:
NA
s in col_val
result in missing values for the merged
-column (e.g., NA
+ 0.1
= NA
)
NA
s in col_uncert
(but not col_val
) result in
-base values only for the merged column (e.g.,
-12.0
+ NA
= 12.0
)
NA
s both col_val
and col_uncert
result in
-missing values for the merged column (e.g., NA
+ NA
=
-NA
)
Any resulting NA
values in the col_val
column following the
-merge operation can be easily formatted using the fmt_missing()
-function.
This function is part of a set of three column-merging functions. The other
-two are the general cols_merge()
function and the specialized
-cols_merge_range()
function. These functions operate similarly,
-where the second column specified is dropped from the output table. For all
-of the cols_merge*()
functions, column removal occurs late in the
-rendering lifecycle so those secondary columns are still usable as column
-references (e.g., inside expressions provided to `rows` in the fmt*()
-functions).
Other column modification functions: cols_align
,
- cols_hide
, cols_label
,
- cols_merge_range
, cols_merge
,
- cols_move_to_end
,
- cols_move_to_start
,
- cols_move
, cols_split_delim
-# Use `exibble` to create a gt table, -# keeping only the `currency` and `num` -# columns; merge columns into one with -# a base value and uncertainty (after -# formatting the `num` column) -tab_1 <- - exibble %>% - dplyr::select(currency, num) %>% - dplyr::slice(1:7) %>% - gt() %>% - fmt_number( - columns = vars(num), - decimals = 3, - use_seps = FALSE - ) %>% - cols_merge_uncert( - col_val = vars(currency), - col_uncert = vars(num) - ) %>% - cols_label( - currency = "value + uncert.")
On those occasions where you need to move columns this way or that way, we
-can make use of the cols_move()
function. While it's true that the
-movement of columns can be done upstream of gt's API, it is much easier
-and less error prone to use the function provided here. The movement
-procedure here takes one or more specified columns (in the columns
-argument) and places them to the right of a different column (the
-after
argument). The ordering of the columns
to be moved is
-preserved, as is the ordering of all other columns in the table.
cols_move(data, columns, after)- -
data | -a table object that is created using the |
-
---|---|
columns | -the column names to move to as a group to a different -position. The order of the remaining columns will be preserved. |
-
after | -a column name used to anchor the insertion of the moved columns. -All of the moved columns will be placed to the right of this column. |
-
an object of class gt_tbl
.
The columns supplied in columns
must all exist in the table and none
-of them can be in the after
argument. The after
column must
-also exist and only one column should be provided here. If you need to place
-one or columns at the beginning of the column series, the
-cols_move_to_start()
function should be used. Similarly, if
-those columns to move should be placed at the end of the column series then
-use cols_move_to_end()
.
Other column modification functions: cols_align
,
- cols_hide
, cols_label
,
- cols_merge_range
,
- cols_merge_uncert
,
- cols_merge
, cols_move_to_end
,
- cols_move_to_start
,
- cols_split_delim
-# Use `countrypops` to create a gt table; -# With the remaining columns, position -# `population` after `country_name` -tab_1 <- - countrypops %>% - dplyr::select(-contains("code")) %>% - dplyr::filter(country_name == "Mongolia") %>% - tail(5) %>% - gt() %>% - cols_move( - columns = vars(population), - after = vars(country_name) - )
It's possible to move a set of columns to the end of the column series, we
-only need to specify which columns
are to be moved. While this can be
-done upstream of gt's API, this function makes to process much easier
-and it's less error prone. The ordering of the columns
that are moved
-to the end is preserved (same with the ordering of all other columns in the
-table).
cols_move_to_end(data, columns)- -
data | -a table object that is created using the |
-
---|---|
columns | -the column names to move to the right-most side of the table. -The order in which columns are provided will be preserved (as is the case -with the remaining columns). |
-
an object of class gt_tbl
.
The columns supplied in columns
must all exist in the table. If you
-need to place one or columns at the start of the column series, the
-cols_move_to_start()
function should be used. More control is
-offered with the cols_move()
function, where columns could be
-placed after a specific column.
Other column modification functions: cols_align
,
- cols_hide
, cols_label
,
- cols_merge_range
,
- cols_merge_uncert
,
- cols_merge
,
- cols_move_to_start
,
- cols_move
, cols_split_delim
-# Use `countrypops` to create a gt table; -# With the remaining columns, move the -# `year` column to the end -tab_1 <- - countrypops %>% - dplyr::select(-contains("code")) %>% - dplyr::filter(country_name == "Mongolia") %>% - tail(5) %>% - gt() %>% - cols_move_to_end( - columns = vars(year) - ) - -# Use `countrypops` to create a gt table; -# With the remaining columns, move `year` -# and `country_name` to the end -tab_2 <- - countrypops %>% - dplyr::select(-contains("code")) %>% - dplyr::filter(country_name == "Mongolia") %>% - tail(5) %>% - gt() %>% - cols_move_to_end( - columns = vars(year, country_name) - )
We can easily move set of columns to the beginning of the column series and
-we only need to specify which columns
. It's possible to do this
-upstream of gt's API, however, it is easier with this function and it
-presents less possibility for error. The ordering of the columns
that
-are moved to the start is preserved (same with the ordering of all other
-columns in the table).
cols_move_to_start(data, columns)- -
data | -a table object that is created using the |
-
---|---|
columns | -the column names to move to the left-most side of the table. -The order in which columns are provided will be preserved (as is the case -with the remaining columns). |
-
an object of class gt_tbl
.
The columns supplied in columns
must all exist in the table. If you
-need to place one or columns at the end of the column series, the
-cols_move_to_end()
function should be used. More control is
-offered with the cols_move()
function, where columns could be
-placed after a specific column.
Other column modification functions: cols_align
,
- cols_hide
, cols_label
,
- cols_merge_range
,
- cols_merge_uncert
,
- cols_merge
, cols_move_to_end
,
- cols_move
, cols_split_delim
-# Use `countrypops` to create a gt table; -# With the remaining columns, move the -# `year` column to the start -tab_1 <- - countrypops %>% - dplyr::select(-contains("code")) %>% - dplyr::filter(country_name == "Mongolia") %>% - tail(5) %>% - gt() %>% - cols_move_to_start( - columns = vars(year) - ) - -# Use `countrypops` to create a gt table; -# With the remaining columns, move `year` -# and `population` to the start -tab_2 <- - countrypops %>% - dplyr::select(-contains("code")) %>% - dplyr::filter(country_name == "Mongolia") %>% - tail(5) %>% - gt() %>% - cols_move_to_start( - columns = vars(year, population) - )
R/modify_columns.R
- cols_split_delim.Rd
This function will split selected delimited column names such that the first -components (LHS) are promoted to being spanner column labels, and the -secondary components (RHS) will become the column labels. Please note that -reference to individual columns must continue to be the column names from the -input table data (which are unique by necessity).
- -cols_split_delim(data, delim, columns = NULL)- -
data | -a table object that is created using the |
-
---|---|
delim | -the delimiter to use to split an input column name. The -delimiter supplied will be autoescaped for the internal splitting -procedure. The first component of the split will become the group name and -the second component will be the column label. |
-
columns | -an optional vector of column names that this operation should -be limited to. The default is to consider all columns in the table. |
-
an object of class gt_tbl
.
If we look to the column names in the iris
dataset as an example of
-how cols_split_delim()
might be useful, we find the names
-Sepal.Length
, Sepal.Width
, Petal.Length
,
-Petal.Width
. From this naming system, it's easy to see that the
-Sepal
and Petal
can group together the repeated common
-Length
and Width
values. In your own datasets, we can avoid a
-lengthy relabeling with cols_label()
if column names can be
-fashioned beforehand to contain both the spanner column label and the column
-label. An additional advantage is that the column names in the input table
-data remain unique even though there may eventually be repeated column labels
-in the rendered output table).
Other column modification functions: cols_align
,
- cols_hide
, cols_label
,
- cols_merge_range
,
- cols_merge_uncert
,
- cols_merge
, cols_move_to_end
,
- cols_move_to_start
, cols_move
-
A dataset that presents yearly, total populations of countries. Total
-population is based on counts of all residents regardless of legal status or
-citizenship. Country identifiers include the English-language country names,
-and the 2- and 3-letter ISO 3166-1 country codes. Each row contains a
-population
value for a given year
(from 1960 to 2017). Any
-NA
values for populations
indicate the non-existence of the
-country during that year.
countrypops
-
- A tibble with 12470 rows and 5 variables:
Name of the country
The 2-letter ISO 3166-1 country code
The 3-letter ISO 3166-1 country code
The year for the population estimate
The population estimate, midway through the year
https://data.worldbank.org/indicator/SP.POP.TOTL
- - --#> Observations: 12,470 -#> Variables: 5 -#> $ country_name <chr> "Aruba", "Aruba", "Aruba", "Aruba", "Aruba", "Aruba", ā¦ -#> $ country_code_2 <chr> "AW", "AW", "AW", "AW", "AW", "AW", "AW", "AW", "AW", ā¦ -#> $ country_code_3 <chr> "ABW", "ABW", "ABW", "ABW", "ABW", "ABW", "ABW", "ABW"ā¦ -#> $ year <int> 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, ā¦ -#> $ population <int> 54211, 55438, 56225, 56695, 57032, 57360, 57715, 58055ā¦
R/data_color.R
- data_color.Rd
It's possible to add color to data cells according to their values. The
-data_color()
function colors all rows of any columns
supplied.
-There are two ways to define how cells are colored: (1) through the use of a
-supplied color palette, and (2) through use of a color mapping function
-available from the scales
package. The first method colorizes cell
-data according to whether values are character or numeric. The second method
-provides more control over how cells are colored since we provide an explicit
-color function and thus other requirements such as bin counts, cut points, or
-a numeric domain. Finally, we can choose whether to apply the cell-specific
-colors to either the cell background or the cell text.
data_color(data, columns, colors, alpha = NULL, apply_to = "bkgd", - autocolor_text = TRUE)- -
data | -a table object that is created using the |
-
---|---|
columns | -the columns wherein changes to cell data colors should occur. |
-
colors | -either a color mapping function from the |
-
alpha | -an optional, fixed alpha transparency value that will be applied
-to all of the |
-
apply_to | -which style element should the colors be applied to? Options
-include the cell background (the default, given as |
-
autocolor_text | -an option to let gt modify the coloring of text
-within cells undergoing background coloring. This will in some cases yield
-more optimal text-to-background color contrast. By default, this is set to
- |
-
an object of class gt_tbl
.
The col_*()
functions from the scales package can be used in the
-colors
argument. These functions map data values (numeric
or
-factor
/character
) to colors according to the provided palette.
col_numeric()
: provides a simple linear mapping
-from continuous numeric data to an interpolated palette.
col_bin()
: provides a mapping of continuous
-numeric data to value-based bins. This internally uses the
-cut()
function.
col_quantile()
: provides a mapping of continuous
-numeric data to quantiles. This internally uses the
-quantile()
function.
col_factor()
: provides a mapping of factors to
-colors. If the palette is discrete and has a different number of colors than
-the number of factors, interpolation is used.
By default, gt will choose the ideal text color (for maximal contrast)
-when colorizing the background of data cells. This option can be disabled by
-setting autocolor_text
to FALSE
.
Choosing the right color palette can often be difficult because it's both
-hard to discover suitable palettes and then obtain the vector of colors. To
-make this process easier we can elect to use the paletteer package,
-which makes a wide range of palettes from various R packages readily
-available. The info_paletteer()
information table allows us to
-easily inspect all of the discrete color palettes available in
-paletteer. We only then need to specify the package
and
-palette
when calling the paletteer::paletteer_d()
function,
-and, we get the palette as a vector of hexadecimal colors.
Other data formatting functions: fmt_currency
,
- fmt_datetime
, fmt_date
,
- fmt_missing
, fmt_number
,
- fmt_passthrough
, fmt_percent
,
- fmt_scientific
, fmt_time
,
- fmt
, text_transform
-# library(paletteer) - -# Use `countrypops` to create a gt table; -# Apply a color scale to the `population` -# column with `scales::col_numeric`, -# four supplied colors, and a domain -tab_1 <- - countrypops %>% - dplyr::filter(country_name == "Mongolia") %>% - dplyr::select(-contains("code")) %>% - tail(10) %>% - gt() %>% - data_color( - columns = vars(population), - colors = scales::col_numeric( - palette = c( - "red", "orange", "green", "blue"), - domain = c(0.2E7, 0.4E7)) - ) - -# Use `pizzaplace` to create a gt table; -# Apply colors from the `red_material` -# palette (in the `ggsci` pkg but -# more easily gotten from the `paletteer` -# package, info at `info_paletteer()`) to -# to `sold` and `income` columns; setting -# the `domain` of `scales::col_numeric()` -# to `NULL` will use the bounds of the -# available data as the domain -tab_2 <- - pizzaplace %>% - dplyr::filter( - type %in% c("chicken", "supreme")) %>% - dplyr::group_by(type, size) %>% - dplyr::summarize( - sold = n(), - income = sum(price) - ) %>% - gt(rowname_col = "size") %>% - data_color( - columns = vars(sold, income), - colors = scales::col_numeric( - palette = paletteer::paletteer_d( - package = "ggsci", - palette = "red_material" - ), - domain = NULL) - )
Text may contain several characters with special meanings in LaTeX. This -function will transform a character vector so that it is safe to use within -LaTeX tables.
- -escape_latex(text)- -
text | -a character vector containing the text that is to be -LaTeX-escaped. |
-
---|
Other helper functions: cells_styles
,
- gt_latex_dependencies
, html
,
- md
, pct
, px
This tibble contains data of a few different classes, which makes it
-well-suited for quick experimentation with the functions in this package. It
-contains only eight rows with numeric, character, and factor columns. The
-last 4 rows contain NA
values in the majority of this tibble's columns
-(1 missing value per column). The date
, time
, and
-datetime
columns are character-based dates/times in the familiar ISO
-8601 format. The row
and group
columns provide for unique
-rownames and two groups (grp_a
and grp_b
) for experimenting
-with the gt()
function's rowname_col
and
-groupname_col
arguments.
exibble
-
- A tibble with 8 rows and 9 variables:
a numeric column ordered with increasingly larger values
a character column composed of names of fruits from a
to
- h
a factor column with numbers from 1 to 8, written out
character columns with dates, times, and - datetimes
a numeric column that is useful for testing currency-based - formatting
a character column in the format row_X
which can be
- useful for testing with row captions in a table stub
a character column with four grp_a
values and four
- grp_b
values which can be useful for testing tables that contain
- row groups
-#> Observations: 8 -#> Variables: 9 -#> $ num <dbl> 1.111e-01, 2.222e+00, 3.333e+01, 4.444e+02, 5.550e+03, NA, 7ā¦ -#> $ char <chr> "apricot", "banana", "coconut", "durian", NA, "fig", "grapefā¦ -#> $ fctr <fct> one, two, three, four, five, six, seven, eight -#> $ date <chr> "2015-01-15", "2015-02-15", "2015-03-15", "2015-04-15", "201ā¦ -#> $ time <chr> "13:35", "14:40", "15:45", "16:50", "17:55", NA, "19:10", "2ā¦ -#> $ datetime <chr> "2018-01-01 02:22", "2018-02-02 14:33", "2018-03-03 03:44", ā¦ -#> $ currency <dbl> 49.950, 17.950, 1.390, 65100.000, 1325.810, 13.255, NA, 0.440 -#> $ row <chr> "row_1", "row_2", "row_3", "row_4", "row_5", "row_6", "row_7ā¦ -#> $ group <chr> "grp_a", "grp_a", "grp_a", "grp_a", "grp_b", "grp_b", "grp_bā¦
Get a list of summary row data frames from a gt_tbl
object where
-summary rows were added via the summary_rows()
function. The
-output data frames contain the groupname
and rowname
columns,
-whereby rowname
contains descriptive stub labels for the summary rows.
extract_summary(data)- -
data | -a table object that is created using the |
-
---|
a list of data frames containing summary data.
- -Other table export functions: as_latex
,
- as_raw_html
, as_rtf
-# Use `sp500` to create a gt table with -# row groups; create summary rows by row -# group (`min`, `max`, `avg`) and then -# extract the summary rows as a list -# object -summary_extracted <- - sp500 %>% - dplyr::filter( - date >= "2015-01-05" & - date <="2015-01-30" - ) %>% - dplyr::arrange(date) %>% - dplyr::mutate( - week = paste0( - "W", strftime(date, format = "%V")) - ) %>% - dplyr::select(-adj_close, -volume) %>% - gt( - rowname_col = "date", - groupname_col = "week" - ) %>% - summary_rows( - groups = TRUE, - columns = vars(open, high, low, close), - fns = list( - min = ~min(.), - max = ~max(.), - avg = ~mean(.)), - formatter = fmt_number, - use_seps = FALSE - ) %>% - extract_summary() - -# Use the summary list to make a new -# gt table; the key thing is to use -# `dplyr::bind_rows()` and then pass the -# tibble to `gt()` (the `groupname` and -# `rowname` magic column names create -# row groups and a stub) -tab_1 <- - summary_extracted %>% - dplyr::bind_rows() %>% - gt()
The fmt()
function provides greater control in formatting raw data
-values than any of the specialized fmt_*()
functions that are
-available in gt. Along with the columns
and rows
-arguments that provide some precision in targeting data cells, the fns
-argument allows you to define one or more functions for manipulating the raw
-data.
fmt(data, columns = NULL, rows = NULL, fns)- -
data | -a table object that is created using the |
-
---|---|
columns | -the columns to format. Can either be a series of column names
-provided in |
-
rows | -optional rows to format. Not providing any value results in all
-rows in |
-
fns | -a single formatting function or a named list of functions. |
-
an object of class gt_tbl
.
If providing a single function to fns
, the recommended format is in
-the form: fns = function(x) ...
. This single function will format the
-targeted data cells the same way regardless of the output format (e.g., HTML,
-LaTeX, RTF).
If you require formatting of x
that depends on the output format, a
-list of functions can be provided for the html
, latex
, and
-default
contexts. This can be in the form of fns = list(html =
-function(x) ..., latex = function(x) ..., default = function(x) ...)
. In
-this multiple-function case, we recommended including the default
-function as a fallback if all contexts aren't provided.
As with all of the fmt_*()
functions, targeting of values is done
-through columns
and additionally by rows
(if nothing is
-provided for rows
then entire columns are selected). A number of
-helper functions exist to make targeting more effective. Conditional
-formatting is possible by providing a conditional expression to the
-rows
argument. See the Arguments section for more information on this.
Other data formatting functions: data_color
,
- fmt_currency
, fmt_datetime
,
- fmt_date
, fmt_missing
,
- fmt_number
, fmt_passthrough
,
- fmt_percent
, fmt_scientific
,
- fmt_time
, text_transform
-
With numeric values in a gt table, we can perform currency-based -formatting. This function supports both automatic formatting with a -three-letter currency code and numeric formatting facilitated through the use -of a locale ID. For fine control the conversion from numeric to currency -values, we can take advantage of the following options:
the currency: providing a currency code or common currency name will -procure the correct currency symbol and number of currency subunits
currency symbol placement: the currency symbol can be placed before -or after the values
decimals/subunits: choice of the number of decimal places, and a -choice of the decimal symbol, and an option on whether to include or exclude -the currency subunits (decimal portion)
negative values: choice of a negative sign or parentheses for values -less than zero
digit grouping separators: options to enable/disable digit separators -and provide a choice of separator symbol
scaling: we can choose to scale targeted values by a multiplier value
pattern: option to use a text pattern for decoration of the formatted -currency values
locale-based formatting: providing a locale ID will result in -currency formatting specific to the chosen locale
fmt_currency(data, columns, rows = NULL, currency = "USD", - use_subunits = TRUE, negative_val = "signed", decimals = NULL, - use_seps = TRUE, scale_by = 1, pattern = "{x}", sep_mark = ",", - dec_mark = ".", placement = "left", incl_space = FALSE, - locale = NULL)- -
data | -a table object that is created using the |
-
---|---|
columns | -the columns to format. Can either be a series of column names
-provided in |
-
rows | -optional rows to format. Not providing any value results in all
-rows in |
-
currency | -the currency to use for the numeric value. This input can be
-supplied as a 3-letter currency code (e.g., |
-
use_subunits | -an option for whether the subunits portion of a currency -value should be displayed. |
-
negative_val | -the formatting to use for negative values. With
- |
-
decimals | -an option to specify the exact number of decimal places to
-use. The default number of decimal places is |
-
use_seps | -an option to use digit group separators. The type of digit
-group separator is set by |
-
scale_by | -a value to scale the input. The default is |
-
pattern | -a formatting pattern that allows for decoration of the
-formatted value. The value itself is represented by |
-
sep_mark | -the mark to use as a separator between groups of digits
-(e.g., using |
-
dec_mark | -the character to use as a decimal mark (e.g., using
- |
-
placement | -the placement of the currency symbol. This can be either be
- |
-
incl_space | -an option on whether to include a space between the value -and the currency symbol. The default is to not introduce a space character. |
-
locale | -an optional locale ID that can be used for formatting the value
-according the locale's rules. Examples include |
-
an object of class gt_tbl
.
We can use the info_currencies()
function for a useful
-reference on all of the possible inputs to currency
.
Targeting of values is done through columns
and additionally by
-rows
(if nothing is provided for rows
then entire columns are
-selected). A number of helper functions exist to make targeting more
-effective. Conditional formatting is possible by providing a conditional
-expression to the rows
argument. See the Arguments section for more
-information on this.
Other data formatting functions: data_color
,
- fmt_datetime
, fmt_date
,
- fmt_missing
, fmt_number
,
- fmt_passthrough
, fmt_percent
,
- fmt_scientific
, fmt_time
,
- fmt
, text_transform
-# Use `exibble` to create a gt table; -# format the `currency` column to have -# currency values in euros (EUR) -tab_1 <- - exibble %>% - gt() %>% - fmt_currency( - columns = vars(currency), - currency = "EUR" - ) - -# Use `exibble` to create a gt table; -# Keep only the `num` and `currency`, -# columns, then, format those columns -# using the "CNY" and "GBP" currencies -tab_2 <- - exibble %>% - dplyr::select(num, currency) %>% - gt() %>% - fmt_currency( - columns = vars(num), - currency = "CNY" - ) %>% - fmt_currency( - columns = vars(currency), - currency = "GBP" - )
Format input date values that are character-based and expressed according to
-the ISO 8601 date format (YYYY-MM-DD
). Once the appropriate data cells
-are targeted with columns
(and, optionally, rows
), we can
-simply apply a preset date style (see table in
-info_date_style()
for info) to format the dates.
fmt_date(data, columns, rows = NULL, date_style = 2)- -
data | -a table object that is created using the |
-
---|---|
columns | -the columns to format. Can either be a series of column names
-provided in |
-
rows | -optional rows to format. Not providing any value results in all
-rows in |
-
date_style | -the date style to use. Supply a number (from |
-
an object of class gt_tbl
.
The following date styles are available for simpler formatting of ISO dates
-(all using the input date of 2000-02-29
in the example output dates):
iso: 2000-02-29
wday_month_day_year: Tuesday, February 29, 2000
wd_m_day_year: Tue, Feb 29, 2000
wday_day_month_year: Tuesday 29 February 2000
month_day_year: February 29, 2000
m_day_year: Feb 29, 2000
day_m_year: 29 Feb 2000
day_month_year: 29 February 2000
day_month: 29 February
year: 2000
month: February
day: 29
year.mn.day: 2000/02/29
y.mn.day: 0/02/29
We can use the info_date_style()
function for a useful
-reference on all of the possible inputs to date_style
.
Targeting of values is done through columns
and additionally by
-rows
(if nothing is provided for rows
then entire columns are
-selected). A number of helper functions exist to make targeting more
-effective. Conditional formatting is possible by providing a conditional
-expression to the rows
argument. See the Arguments section for more
-information on this.
Other data formatting functions: data_color
,
- fmt_currency
, fmt_datetime
,
- fmt_missing
, fmt_number
,
- fmt_passthrough
, fmt_percent
,
- fmt_scientific
, fmt_time
,
- fmt
, text_transform
-# Use `exibble` to create a gt table; -# keep only the `date` and `time` columns; -# format the `date` column to have -# dates formatted as `month_day_year` -# (date style `5`) -tab_1 <- - exibble %>% - dplyr::select(date, time) %>% - gt() %>% - fmt_date( - columns = vars(date), - date_style = 5 - ) - -# Use `exibble` to create a gt table; -# keep only the `date` and `time` columns; -# format the `date` column to have mixed -# date formats (dates after April will -# be different than the others) -tab_2 <- - exibble %>% - dplyr::select(date, time) %>% - gt() %>% - fmt_date( - columns = vars(date), - rows = - as.Date(date) > as.Date("2015-04-01"), - date_style = 6 - ) %>% - fmt_date( - columns = vars(date), - rows = - as.Date(date) <= as.Date("2015-04-01"), - date_style = 7 - )
Format input date-time values that are character-based and expressed
-according to the ISO 8601 date-time format (YYYY-MM-DD HH:MM:SS
). Once
-the appropriate data cells are targeted with columns
(and, optionally,
-rows
), we can simply apply preset date and time styles (see tables in
-info_date_style()
and info_time_style()
for more
-info) to format the data-time values.
fmt_datetime(data, columns, rows = NULL, date_style = 2, - time_style = 2)- -
data | -a table object that is created using the |
-
---|---|
columns | -the columns to format. Can either be a series of column names
-provided in |
-
rows | -optional rows to format. Not providing any value results in all
-rows in |
-
date_style | -the date style to use. Supply a number (from |
-
time_style | -the time style to use. Supply a number (from |
-
an object of class gt_tbl
.
The following date styles are available for simpler formatting of the date
-portion (all using the input date of 2000-02-29
in the example output
-dates):
iso: 2000-02-29
wday_month_day_year: Tuesday, February 29, 2000
wd_m_day_year: Tue, Feb 29, 2000
wday_day_month_year: Tuesday 29 February 2000
month_day_year: February 29, 2000
m_day_year: Feb 29, 2000
day_m_year: 29 Feb 2000
day_month_year: 29 February 2000
day_month: 29 February
year: 2000
month: February
day: 29
year.mn.day: 2000/02/29
y.mn.day: 0/02/29
The following time styles are available for simpler formatting of the time
-portion (all using the input time of 14:35:00
in the example output
-times):
hms: 14:35:00
hm: 14:35
hms_p: 2:35:00 PM
hm_p: 2:35 PM
h_p: 2 PM
We can use the info_date_style()
and
-info_time_style()
functions as useful references for all of the
-possible inputs to date_style
and time_style
.
Targeting of values is done through columns
and additionally by
-rows
(if nothing is provided for rows
then entire columns are
-selected). A number of helper functions exist to make targeting more
-effective. Conditional formatting is possible by providing a conditional
-expression to the rows
argument. See the Arguments section for more
-information on this.
Other data formatting functions: data_color
,
- fmt_currency
, fmt_date
,
- fmt_missing
, fmt_number
,
- fmt_passthrough
, fmt_percent
,
- fmt_scientific
, fmt_time
,
- fmt
, text_transform
-# Use `exibble` to create a gt table; -# keep only the `datetime` column; -# format the column to have dates -# formatted as `month_day_year` and -# times to be `hms_p` -tab_1 <- - exibble %>% - dplyr::select(datetime) %>% - gt() %>% - fmt_datetime( - columns = vars(datetime), - date_style = 5, - time_style = 3 - )
Wherever there is missing data (i.e., NA
values) a customizable mark
-may present better than the standard NA
text that would otherwise
-appear. The fmt_missing()
function allows for this replacement through
-its missing_text
argument (where an em dash serves as the default).
fmt_missing(data, columns, rows = NULL, missing_text = "---")- -
data | -a table object that is created using the |
-
---|---|
columns | -the columns to format. Can either be a series of column names
-provided in |
-
rows | -optional rows to format. Not providing any value results in all
-rows in |
-
missing_text | -the text to be used in place of |
-
an object of class gt_tbl
.
Targeting of values is done through columns
and additionally by
-rows
(if nothing is provided for rows
then entire columns are
-selected). A number of helper functions exist to make targeting more
-effective. Conditional formatting is possible by providing a conditional
-expression to the rows
argument. See the Arguments section for more
-information on this.
Other data formatting functions: data_color
,
- fmt_currency
, fmt_datetime
,
- fmt_date
, fmt_number
,
- fmt_passthrough
, fmt_percent
,
- fmt_scientific
, fmt_time
,
- fmt
, text_transform
-# Use `exibble` to create a gt table; -# NA values in different columns will -# be given replacement text -tab_1 <- - exibble %>% - dplyr::select(-row, -group) %>% - gt() %>% - fmt_missing( - columns = 1:2, - missing_text = "missing" - ) %>% - fmt_missing( - columns = 4:7, - missing_text = "nothing" - )
With numeric values in a gt table, we can perform number-based -formatting so that the targeted values are rendered with a higher -consideration for tabular presentation. Furthermore, there is finer control -over numeric foramtting with the following options:
decimals: choice of the number of decimal places, option to drop -trailing zeros, and a choice of the decimal symbol
negative values: choice of a negative sign or parentheses for values -less than zero
digit grouping separators: options to enable/disable digit separators -and provide a choice of separator symbol
scaling: we can choose to scale targeted values by a multiplier value
pattern: option to use a text pattern for decoration of the formatted -values
locale-based formatting: providing a locale ID will result in number -formatting specific to the chosen locale
fmt_number(data, columns, rows = NULL, decimals = 2, - drop_trailing_zeros = FALSE, negative_val = "signed", - use_seps = TRUE, scale_by = 1, pattern = "{x}", sep_mark = ",", - dec_mark = ".", locale = NULL)- -
data | -a table object that is created using the |
-
---|---|
columns | -the columns to format. Can either be a series of column names
-provided in |
-
rows | -optional rows to format. Not providing any value results in all
-rows in |
-
decimals | -an option to specify the exact number of decimal places to
-use. The default number of decimal places is |
-
drop_trailing_zeros | -a logical value that allows for removal of -trailing zeros (those redundant zeros after the decimal mark). |
-
negative_val | -the formatting to use for negative values. With
- |
-
use_seps | -an option to use digit group separators. The type of digit
-group separator is set by |
-
scale_by | -a value to scale the input. The default is |
-
pattern | -a formatting pattern that allows for decoration of the
-formatted value. The value itself is represented by |
-
sep_mark | -the mark to use as a separator between groups of digits
-(e.g., using |
-
dec_mark | -the character to use as a decimal mark (e.g., using
- |
-
locale | -an optional locale ID that can be used for formatting the value
-according the locale's rules. Examples include |
-
an object of class gt_tbl
.
Targeting of values is done through columns
and additionally by
-rows
(if nothing is provided for rows
then entire columns are
-selected). A number of helper functions exist to make targeting more
-effective. Conditional formatting is possible by providing a conditional
-expression to the rows
argument. See the Arguments section for more
-information on this.
Other data formatting functions: data_color
,
- fmt_currency
, fmt_datetime
,
- fmt_date
, fmt_missing
,
- fmt_passthrough
, fmt_percent
,
- fmt_scientific
, fmt_time
,
- fmt
, text_transform
-# Use `exibble` to create a gt table; -# format the `num` column as numeric -# with three decimal places and with no -# use of digit separators -tab_1 <- - exibble %>% - gt() %>% - fmt_number( - columns = vars(num), - decimals = 3, - use_seps = FALSE - ) - -# Use `exibble` to create a gt table; -# format the `num` column as numeric, -# but treating the first four rows -# different than the last four -tab_2 <- - exibble %>% - gt() %>% - fmt_number( - columns = vars(num), - rows = 1:4, - decimals = 2) %>% - fmt_number( - columns = vars(num), - rows = 5:8, - decimals = 1, - scale_by = 1/1000, - pattern = "{x}K")
Format by passing data through no other transformation other than: (1)
-coercing to character
(as all the fmt_*()
functions do), and
-(2) applying prefixed or suffixed text via the pattern
argument (the
-default is to apply nothing). All of this is useful when don't want to modify
-the input data other than to decorate it within a pattern. Also, this
-function is useful when used as a formatter
function in the
-summary_rows
function, where the output may be text or useful as is
-(that function requires a formatter function).
fmt_passthrough(data, columns, rows = NULL, escape = TRUE, - pattern = "{x}")- -
data | -a table object that is created using the |
-
---|---|
columns | -the columns to format. Can either be a series of column names
-provided in |
-
rows | -optional rows to format. Not providing any value results in all
-rows in |
-
escape | -an option to escape text according to the final output format
-of the table. For example, if a LaTeX table is to be generated then LaTeX
-escaping would be performed during rendering. By default this is set to
- |
-
pattern | -a formatting pattern that allows for decoration of the
-formatted value. The value itself is represented by |
-
an object of class gt_tbl
.
Targeting of values is done through columns
and additionally by
-rows
(if nothing is provided for rows
then entire columns are
-selected). A number of helper functions exist to make targeting more
-effective. Conditional formatting is possible by providing a conditional
-expression to the rows
argument. See the Arguments section for more
-information on this.
Other data formatting functions: data_color
,
- fmt_currency
, fmt_datetime
,
- fmt_date
, fmt_missing
,
- fmt_number
, fmt_percent
,
- fmt_scientific
, fmt_time
,
- fmt
, text_transform
-# Use `exibble` to create a gt table; -# keep only the `char` column; -# pass the data in that column through -# but apply a simple pattern that adds -# an 's' to the non-NA values -tab_1 <- - exibble %>% - dplyr::select(char) %>% - gt() %>% - fmt_passthrough( - columns = vars(char), - rows = !is.na(char), - pattern = "{x}s" - )
With numeric values in a gt table, we can perform percentage-based
-formatting. It is assumed the input numeric values are in a fractional format
-since the will be automatically multplied by 100
before decorating
-with a percent sign. For more control over percentage formatting, we can use
-the following options:
percent sign placement: the percent sign can be placed after or -before the values and a space can be inserted between the symbol and the -value.
decimals: choice of the number of decimal places, option to drop -trailing zeros, and a choice of the decimal symbol
negative values: choice of a negative sign or parentheses for values -less than zero
digit grouping separators: options to enable/disable digit separators -and provide a choice of separator symbol
pattern: option to use a text pattern for decoration of the formatted -values
locale-based formatting: providing a locale ID will result in number -formatting specific to the chosen locale
fmt_percent(data, columns, rows = NULL, decimals = 2, - drop_trailing_zeros = FALSE, negative_val = "signed", - use_seps = TRUE, pattern = "{x}", sep_mark = ",", dec_mark = ".", - incl_space = FALSE, placement = "right", locale = NULL)- -
data | -a table object that is created using the |
-
---|---|
columns | -the columns to format. Can either be a series of column names
-provided in |
-
rows | -optional rows to format. Not providing any value results in all
-rows in |
-
decimals | -an option to specify the exact number of decimal places to
-use. The default number of decimal places is |
-
drop_trailing_zeros | -a logical value that allows for removal of -trailing zeros (those redundant zeros after the decimal mark). |
-
negative_val | -the formatting to use for negative values. With
- |
-
use_seps | -an option to use digit group separators. The type of digit
-group separator is set by |
-
pattern | -a formatting pattern that allows for decoration of the
-formatted value. The value itself is represented by |
-
sep_mark | -the mark to use as a separator between groups of digits
-(e.g., using |
-
dec_mark | -the character to use as a decimal mark (e.g., using
- |
-
incl_space | -an option on whether to include a space between the value -and the percent sign. The default is to not introduce a space character. |
-
placement | -the placement of the percent sign. This can be either be
- |
-
locale | -an optional locale ID that can be used for formatting the value
-according the locale's rules. Examples include |
-
an object of class gt_tbl
.
Targeting of values is done through columns
and additionally by
-rows
(if nothing is provided for rows
then entire columns are
-selected). A number of helper functions exist to make targeting more
-effective. Conditional formatting is possible by providing a conditional
-expression to the rows
argument. See the Arguments section for more
-information on this.
Other data formatting functions: data_color
,
- fmt_currency
, fmt_datetime
,
- fmt_date
, fmt_missing
,
- fmt_number
, fmt_passthrough
,
- fmt_scientific
, fmt_time
,
- fmt
, text_transform
-
With numeric values in a gt table, we can perform formatting so that -the targeted values are presented in scientific notation. We can exert finer -finer control on the formatting with the following options:
decimals: choice of the number of decimal places, option to drop -trailing zeros, and a choice of the decimal symbol
scaling: we can choose to scale targeted values by a multiplier value
pattern: option to use a text pattern for decoration of the formatted -values
locale-based formatting: providing a locale ID will result in -formatting specific to the chosen locale
fmt_scientific(data, columns, rows = NULL, decimals = 2, - drop_trailing_zeros = FALSE, scale_by = 1, pattern = "{x}", - sep_mark = ",", dec_mark = ".", locale = NULL)- -
data | -a table object that is created using the |
-
---|---|
columns | -the columns to format. Can either be a series of column names
-provided in |
-
rows | -optional rows to format. Not providing any value results in all
-rows in |
-
decimals | -an option to specify the exact number of decimal places to
-use. The default number of decimal places is |
-
drop_trailing_zeros | -a logical value that allows for removal of -trailing zeros (those redundant zeros after the decimal mark). |
-
scale_by | -a value to scale the input. The default is |
-
pattern | -a formatting pattern that allows for decoration of the
-formatted value. The value itself is represented by |
-
sep_mark | -the mark to use as a separator between groups of digits
-(e.g., using |
-
dec_mark | -the character to use as a decimal mark (e.g., using
- |
-
locale | -an optional locale ID that can be used for formatting the value
-according the locale's rules. Examples include |
-
an object of class gt_tbl
.
Targeting of values is done through columns
and additionally by
-rows
(if nothing is provided for rows
then entire columns are
-selected). A number of helper functions exist to make targeting more
-effective. Conditional formatting is possible by providing a conditional
-expression to the rows
argument. See the Arguments section for more
-information on this.
Other data formatting functions: data_color
,
- fmt_currency
, fmt_datetime
,
- fmt_date
, fmt_missing
,
- fmt_number
, fmt_passthrough
,
- fmt_percent
, fmt_time
,
- fmt
, text_transform
-# Use `exibble` to create a gt table; -# format the `num` column as partially -# numeric and partially in scientific -# notation -tab_1 <- - exibble %>% - gt() %>% - fmt_number( - columns = vars(num), - rows = num > 500, - decimals = 1, - scale_by = 1/1000, - pattern = "{x}K" - ) %>% - fmt_scientific( - columns = vars(num), - rows = num <= 500, - decimals = 1 - )
Format input time values that are character-based and expressed according to
-the ISO 8601 time format (HH:MM:SS
). Once the appropriate data cells
-are targeted with columns
(and, optionally, rows
), we can
-simply apply a preset time style (see table in
-info_time_style()
for info) to format the times.
fmt_time(data, columns, rows = NULL, time_style = 2)- -
data | -a table object that is created using the |
-
---|---|
columns | -the columns to format. Can either be a series of column names
-provided in |
-
rows | -optional rows to format. Not providing any value results in all
-rows in |
-
time_style | -the time style to use. Supply a number (from |
-
The following time styles are available for simpler formatting of ISO times
-(all using the input time of 14:35:00
in the example output times):
hms: 14:35:00
hm: 14:35
hms_p: 2:35:00 PM
hm_p: 2:35 PM
h_p: 2 PM
We can use the info_time_style()
function for a useful
-reference on all of the possible inputs to time_style
.
Targeting of values is done through columns
and additionally by
-rows
(if nothing is provided for rows
then entire columns are
-selected). A number of helper functions exist to make targeting more
-effective. Conditional formatting is possible by providing a conditional
-expression to the rows
argument. See the Arguments section for more
-information on this.
Other data formatting functions: data_color
,
- fmt_currency
, fmt_datetime
,
- fmt_date
, fmt_missing
,
- fmt_number
, fmt_passthrough
,
- fmt_percent
, fmt_scientific
,
- fmt
, text_transform
-# Use `exibble` to create a gt table; -# keep only the `date` and `time` columns; -# format the `time` column to have -# times formatted as `hms_p` -# (time style `3`) -tab_1 <- - exibble %>% - dplyr::select(date, time) %>% - gt() %>% - fmt_time( - columns = vars(time), - time_style = 3 - ) - -# Use `exibble` to create a gt table; -# keep only the `date` and `time` columns; -# format the `time` column to have mixed -# time formats (times after 16:00 will -# be different than the others) -tab_2 <- - exibble %>% - dplyr::select(date, time) %>% - gt() %>% - fmt_time( - columns = vars(time), - rows = - time > "16:00", - time_style = 3 - ) %>% - fmt_time( - columns = vars(time), - rows = - time <= "16:00", - time_style = 4 - )
We can add a ggplot2 plot inside of a table with the help of the
-ggplot_image()
function. The function provides a convenient way to
-generate an HTML fragment with a ggplot
object. Because this function
-is currently HTML-based, it is only useful for HTML table output. To use this
-function inside of data cells, it is recommended that the
-text_transform()
function is used. With that function, we can
-specify which data cells to target and then include a call to
-ggplot_image()
within the required user-defined function (for the
-fn
argument). If we want to include a plot in other places (e.g., in
-the header, within footnote text, etc.) we need to use ggplot_image()
-within the html()
helper function.
ggplot_image(plot_object, height = 100, aspect_ratio = 1)- -
plot_object | -a ggplot plot object. |
-
---|---|
height | -the absolute height (px) of the image in the table cell. |
-
aspect_ratio | -the plot's final aspect ratio. Where the height of the
-plot is fixed using the |
-
a character object with an HTML fragment that can be placed inside of - a cell.
- -By itself, the function creates an HTML image tag with an image URI embedded
-within (a 100 dpi PNG). We can easily experiment with any ggplot2
plot
-object, and using it within ggplot_image(plot_object = <plot object>
-evaluates to:
<img cid=<random CID> src=<data URI> style=\"height:100px;\">
where a height of 100px
is a default height chosen to work well within
-the heights of most table rows. There is the option to modify the aspect
-ratio of the plot (the default aspect_ratio
is 1.0
) and this is
-useful for elongating any given plot to fit better within the table
-construct.
Other image addition functions: local_image
,
- test_image
, web_image
-library(ggplot2) - -# Create a ggplot plot -plot_object <- - ggplot( - data = gtcars, - aes(x = hp, y = trq, - size = msrp)) + - geom_point(color = "blue") + - theme(legend.position = "none") - -# Create a tibble that contains two -# cells (where one is a placeholder for -# an image), then, create a gt table; -# use the `text_transform()` function -# to insert the plot using by calling -# `ggplot_object()` within the user- -# defined function -tab_1 <- - dplyr::tibble( - text = "Here is a ggplot:", - ggplot = NA - ) %>% - gt() %>% - text_transform( - locations = cells_data(vars(ggplot)), - fn = function(x) { - plot_object %>% - ggplot_image(height = px(200)) - } - )
Build display tables from tabular data using with an easy-to-use - API. With its progressive approach, we can construct display tables with a - clear separation of concerns: you don't have to decide how the tabular data - gets transformed and structured whilst also worrying about aesthetics.
- -Useful links:
Report bugs at https://github.com/rstudio/gt/issues
The gt()
function creates a gt table object when provided with
-table data. Using this function is the first step in a typical gt
-workflow. Once we have the gt table object, we can perform styling
-transformations before rendering to a display table of various formats (e.g.,
-HTML, LaTeX, RTF).
gt(data, rowname_col = "rowname", groupname_col = "groupname", - rownames_to_stub = FALSE, - stub_group.sep = getOption("gt.stub_group.sep", " - "))- -
data | -a |
-
---|---|
rowname_col | -the column name in the input |
-
groupname_col | -the column name in the input |
-
rownames_to_stub | -an option to take rownames from the input |
-
stub_group.sep | -the separator to use between consecutive group names (a
-possibility when providing |
-
an object of class gt_tbl
.
There are a few data ingest options we can consider at this stage. We can
-choose to create a table stub with rowname captions using the
-rowname_col
argument. Further to this, stub row groups can be created
-with the groupname_col
. Both arguments take the name of a column in
-the input table data. Typically, the data in the groupname_col
will
-consist of categories of data in a table and the data in the
-rowname_col
are unique labels (perhaps unique across the entire table
-or unique within groups).
Row groups can also be created by passing a grouped_df
to gt()
-by using the dplyr::group_by()
function on the table data. In this
-way, two or more columns of categorical data can be used to make row groups.
-The stub_group.sep
argument allows for control in how the row group
-label will appear in the display table.
Other table-part creation/modification functions: gt_preview
,
- tab_footnote
, tab_header
,
- tab_options
, tab_row_group
,
- tab_source_note
, tab_spanner
,
- tab_stubhead_label
, tab_style
-# Create a table object using the -# `exibble` dataset; use the `row` -# and `group` columns to add a stub -# and row groups -tab_1 <- - exibble %>% - gt( - rowname_col = "row", - groupname_col = "group" - ) - -# The resulting object can be used -# in transformations (with `tab_*()`, -# `fmt_*()`, `cols_*()` functions) -tab_2 <- - tab_1 %>% - tab_header( - title = "Table Title", - subtitle = "Subtitle" - ) %>% - fmt_number( - columns = vars(num), - decimals = 2 - ) %>% - cols_label(num = "number")
R/helpers.R
- gt_latex_dependencies.Rd
When working with Rnw (Sweave) files or otherwise writing LaTeX code,
-including a gt table can be problematic if we don't have knowledge
-of the LaTeX dependencies. For the most part, these dependencies are the
-LaTeX packages that are required for rendering a gt table. The
-gt_latex_dependencies()
function provides an object that can be
-used to provide the LaTeX in an Rnw file, allowing gt tables to work
-and not yield errors due to missing packages.
gt_latex_dependencies()
-
- Here is an example Rnw document that shows how the
-gt_latex_dependencies()
can be used in conjunction with a gt
-table:
-%!sweave=knitr - \documentclass{article} - <<echo=FALSE>>= -library(gt) - @ - <<results='asis', echo=FALSE>>= -gt_latex_dependencies() - @ - \begin{document} - <<results='asis', echo=FALSE>>= -exibble - @ - \end{document} -- -
Other helper functions: cells_styles
,
- escape_latex
, html
,
- md
, pct
, px
Sometimes you may want to see just a small portion of your input data. We can
-use gt_preview()
in place of gt()
to get the first x
-rows of data and the last y rows of data (which can be set by the
-top_n
and bottom_n
arguments). It's not advised to use
-additional gt API functions to further modify the output of
-gt_preview()
. Furthermore, you cannot pass a gt object to
-gt_preview()
.
gt_preview(data, top_n = 5, bottom_n = 1, incl_rownums = TRUE)- -
data | -a |
-
---|---|
top_n | -this value will be used as the number of rows from the top of
-the table to display. The default, |
-
bottom_n | -the value will be used as the number of rows from the bottom
-of the table to display. The default, |
-
incl_rownums | -an option to include the row numbers for |
-
an object of class gt_tbl
.
Any grouped data or magic columns such as rowname
and groupname
-will be ignored by gt_preview()
and, as such, one cannot add a stub or
-group rows in the output table. By default, the output table will include row
-numbers in a stub (including a range of row numbers for the omitted rows).
-This row numbering option can be deactivated by setting incl_rownums
-to FALSE
.
Other table-part creation/modification functions: gt
,
- tab_footnote
, tab_header
,
- tab_options
, tab_row_group
,
- tab_source_note
, tab_spanner
,
- tab_stubhead_label
, tab_style
-# Use `gtcars` to create a gt table -# preview (with only a few of its -# columns); you'll see the first five -# rows and the last row -tab_1 <- - gtcars %>% - dplyr::select(mfr, model, year) %>% - gt_preview()
Expensive and fast cars. Not your father's mtcars
. Each row describes
-a car of a certain make, model, year, and trim. Basic specifications such as
-horsepower, torque, EPA MPG ratings, type of drivetrain, and transmission
-characteristics are provided. The country of origin for the car manufacturer
-is also given.
gtcars
-
- A tibble with 47 rows and 15 variables:
The name of the car manufacturer
The car's model name
The car's model year
A short description of the car model's trim
An identifier of the car's body style, which is either
- coupe
, convertible
, sedan
, or hatchback
The car's horsepower and the associated RPM level
The car's torque and the associated RPM level
The miles per gallon fuel efficiency rating for city - and highway driving
The car's drivetrain which, for this dataset is either
- rwd
(Rear Wheel Drive) or awd
(All Wheel Drive)
The codified transmission type, where the number part is
- the number of gears; the car could have automatic transmission
- (a
), manual transmission (m
), an option to switch between
- both types (am
), or, direct drive (dd
)
The country name for where the vehicle manufacturer - is headquartered
Various pages within https://www.edmunds.com.
- - --#> Observations: 47 -#> Variables: 15 -#> $ mfr <chr> "Ford", "Ferrari", "Ferrari", "Ferrari", "Ferrari", "Ferrā¦ -#> $ model <chr> "GT", "458 Speciale", "458 Spider", "458 Italia", "488 GTā¦ -#> $ year <dbl> 2017, 2015, 2015, 2014, 2016, 2015, 2017, 2015, 2015, 201ā¦ -#> $ trim <chr> "Base Coupe", "Base Coupe", "Base", "Base Coupe", "Base Cā¦ -#> $ bdy_style <chr> "coupe", "coupe", "convertible", "coupe", "coupe", "conveā¦ -#> $ hp <dbl> 647, 597, 562, 562, 661, 553, 680, 652, 731, 949, 573, 54ā¦ -#> $ hp_rpm <dbl> 6250, 9000, 9000, 9000, 8000, 7500, 8250, 8000, 8250, 900ā¦ -#> $ trq <dbl> 550, 398, 398, 398, 561, 557, 514, 504, 509, 664, 476, 43ā¦ -#> $ trq_rpm <dbl> 5900, 6000, 6000, 6000, 3000, 4750, 5750, 6000, 6000, 675ā¦ -#> $ mpg_c <dbl> 11, 13, 13, 13, 15, 16, 12, 11, 11, 12, 21, 16, 11, 16, 1ā¦ -#> $ mpg_h <dbl> 18, 17, 17, 17, 22, 23, 17, 16, 16, 16, 22, 22, 18, 20, 2ā¦ -#> $ drivetrain <chr> "rwd", "rwd", "rwd", "rwd", "rwd", "rwd", "awd", "awd", "ā¦ -#> $ trsmn <chr> "7a", "7a", "7a", "7a", "7a", "7a", "7a", "7a", "7a", "7aā¦ -#> $ ctry_origin <chr> "United States", "Italy", "Italy", "Italy", "Italy", "Itaā¦ -#> $ msrp <dbl> 447000, 291744, 263553, 233509, 245400, 198973, 298000, 2ā¦
Interpret input text as HTML-formatted text
- -html(text, ...)- -
text, ... | -the text that is understood to be HTML text, which is to be -preserved. |
-
---|
a character object that is tagged as an HTML fragment that is not to - be sanitized.
-a character object of class html
.
Other helper functions: cells_styles
,
- escape_latex
,
- gt_latex_dependencies
, md
,
- pct
, px
-# Use `exibble` to create a gt table; -# when adding a title, use the `html()` -# helper to use html formatting -tab_1 <- - exibble %>% - dplyr::select(currency, char) %>% - gt() %>% - tab_header( - title = html("<em>HTML</em>"))
- Create Table- |
- |
---|---|
- - | -Create a gt table object |
-
- - | -Preview a gt table object |
-
- Create/Modify Parts- |
- |
- - | -Add a table header |
-
- - | -Add a spanner column label |
-
- - | -Add a row group |
-
- - | -Add label text to the stubhead |
-
- - | -Add a table footnote |
-
- - | -Add a source note citation |
-
- - | -Modify the table output options |
-
- - | -Add custom styles to one or more cells |
-
- Format Data- |
- |
- - | -Set a column format with a formatter function |
-
- - | -Format numeric values |
-
- - | -Format values to scientific notation |
-
- - | -Format values as a percentage |
-
- - | -Format values as currencies |
-
- - | -Format values as dates |
-
- - | -Format values as times |
-
- - | -Format values as date-times |
-
- - | -Format missing values |
-
- - | -Format by simply passing data through |
-
- - | -Perform targeted text transformation with a function |
-
- - | -Set data cell colors using a palette or a color function |
-
- Modify Columns- |
- |
- - | -Set the alignment of columns |
-
- - | -Hide one or more columns |
-
- - | -Relabel one or more columns |
-
- - | -Merge two columns to a single column |
-
- - | -Merge two columns to a value range column |
-
- - | -Merge two columns to a value & uncertainty column |
-
- - | -Move one or more columns |
-
- - | -Move one or more columns to the end |
-
- - | -Move one or more columns to the start |
-
- - | -Create group names and column labels via delimited names |
-
- Modify Rows- |
- |
- - | -Modify the ordering of any row groups |
-
- Add Rows- |
- |
- - | -Add summary rows using aggregation functions |
-
- Export Table- |
- |
- - | -Get the HTML content of a gt table |
-
- - | -Output a gt object as LaTeX |
-
- - | -Output a gt object as RTF |
-
- - | -Extract a summary list from a gt object |
-
- Shiny Functions-Shiny is great for building interactive web apps with R. Thereās really nothing quite like it. The gt package includes two functions that work nicely with Shiny: a table render function |
- |
- - | -A gt display table render function for use in Shiny |
-
- - | -Create a gt display table output element for Shiny |
-
- Helper Functions-A small assortment of helper functions is available in the gt package. The various |
- |
-
|
- Helpers for targeting multiple cells in different locations |
-
- - | -Helper for defining custom styles for table cells |
-
- - | -Objects exported from other packages |
-
- - | -Interpret input text as Markdown-formatted text |
-
- - | -Interpret input text as HTML-formatted text |
-
- - | -Helper for providing a numeric value as pixels value |
-
- - | -Helper for providing a numeric value as percentage |
-
- - | -Perform LaTeX escaping |
-
- - | -Adjust the luminance for a palette of colors |
-
- Image Addition- |
- |
- - | -Helper function for adding an image from the web |
-
- - | -Helper function for adding a local image |
-
- - | -Helper function for adding a ggplot |
-
- - | -Generate a path to a test image |
-
- Information-These |
- |
- - | -View a table with info on date styles |
-
- - | -View a table with info on time styles |
-
- - | -View a table with info on many different color palettes |
-
- - | -View a table with info on supported currencies |
-
- Datasets-The gt package is equipped with six datasets. Use them to experiment with the API, they come in all shapes and sizes. Many examples in the internal help documents use these datasets to quickly demonstrate key features of gt. - |
- |
- - | -Yearly populations of countries from 1960 to 2017 |
-
- - | -Twice hourly solar zenith angles by month & latitude |
-
- - | -Deluxe automobiles from the 2014-2017 period |
-
- - | -Daily S&P 500 Index data from 1950 to 2015 |
-
- - | -A year of pizza sales from a pizza place |
-
- - | -A toy example tibble for testing with gt: exibble |
-
The fmt_currency()
function lets us format numeric values as
-currencies. The table generated by the info_currencies()
function
-provides a quick reference to all the available currencies. The currency
-identifiers are provided (name, 3-letter currency code, and 3-digit currency
-code) along with the each currency's exponent value (number of digits of the
-currency subunits). A formatted example is provided (based on the value of
-49.95
) to demonstrate the default formatting of each currency.
info_currencies(type = c("code", "symbol"), begins_with = NULL)- -
type | -the type of currency information provided. Can either be
- |
-
---|---|
begins_with | -providing a single letter will filter currencies to only
-those that begin with that letter in their currency code. The default
-( |
-
There are 172 currencies, which can lead to a verbose display table. To make
-this presentation more focused on retrieval, we can provide an initial letter
-corresponding to the 3-letter currency code to begins_with
. This will
-filter currencies in the info table to just the set beginning with the
-supplied letter.
Other information functions: info_date_style
,
- info_paletteer
,
- info_time_style
-# Get a table of info on all of -# the currencies where the three- -# letter code begins with a "h" -tab_1 <- info_currencies(begins_with = "h") - -# Get a table of info on all of the -# common currency name/symbols that -# can be used with `fmt_currency()` -tab_2 <- info_currencies(type = "symbol")
The fmt_date()
function lets us format date-based values in a
-convenient manner using preset styles. The table generated by the
-info_date_style()
function provides a quick reference to all 14
-styles, with associated number codes, the format names, and example outputs
-using a fixed date (2000-02-29
).
info_date_style()
-
- Other information functions: info_currencies
,
- info_paletteer
,
- info_time_style
-# Get a table of info on the different -# date-formatting styles (which are used -# by supplying a number code to the -# `fmt_date()` function) -tab_1 <- info_date_style()
R/info_tables.R
- info_paletteer.Rd
While the data_color()
function allows us to flexibly color
-data cells in our gt table, the harder part of this process is
-discovering and choosing color palettes that are suitable for the table
-output. We can make this process much easier in two ways: (1) by using the
-paletteer package, which makes a wide range of palettes from various R
-packages readily available, and (2) calling the info_paletteer()
-function to give us an information table that serves as quick reference for
-all of the discrete color palettes available in paletteer.
info_paletteer(color_pkgs = NULL)- -
color_pkgs | -a vector of color packages that determines which sets of
-palettes should be displayed in the information table. If this is
- |
-
---|
The palettes displayed are organized by package and by palette name. These
-values are required when obtaining a palette (as a vector of hexadecimal
-colors), from the the paletteer::paletteer_d()
function. Once we are
-familiar with the names of the color palette packages (e.g.,
-RColorBrewer, ggthemes, wesanderson), we can narrow down
-the content of this information table by supplying a vector package names to
-color_pkgs
.
Other information functions: info_currencies
,
- info_date_style
,
- info_time_style
-# Get a table of info on just the -# `ggthemes` color palette (easily -# accessible from the paletteer pkg) -tab_1 <- - info_paletteer( - color_pkgs = "ggthemes")
The fmt_time()
function lets us format time-based values in a
-convenient manner using preset styles. The table generated by the
-info_time_style()
function provides a quick reference to all five
-styles, with associated number codes, the format names, and example outputs
-using a fixed time (14:35
).
info_time_style()
-
- Other information functions: info_currencies
,
- info_date_style
,
- info_paletteer
-# Get a table of info on the different -# time-formatting styles (which are used -# by supplying a number code to the -# `fmt_time()` function) -tab_1 <- info_time_style()
We can flexibly add a local image (i.e., an image residing on disk) inside of
-a table with local_image()
function. The function provides a
-convenient way to generate an HTML fragment using an on-disk PNG or SVG.
-Because this function is currently HTML-based, it is only useful for HTML
-table output. To use this function inside of data cells, it is recommended
-that the text_transform()
function is used. With that function,
-we can specify which data cells to target and then include a
-local_image()
call within the required user-defined function (for the
-fn
argument). If we want to include an image in other places (e.g., in
-the header, within footnote text, etc.) we need to use local_image()
-within the html()
helper function.
local_image(file, height = 30)- -
file | -a path to an image file. |
-
---|---|
height | -the absolute height (px) of the image in the table cell. |
-
a character object with an HTML fragment that can be placed inside of - a cell.
- -By itself, the function creates an HTML image tag with an image URI embedded
-within. We can easily experiment with a local PNG or SVG image that's
-available in the gt package using the test_image()
-function. Using that, the call local_image(file = test_image(type =
-"png"))
evaluates to:
<img cid=<random CID> src=<data URI> style=\"height:30px;\">
where a height of 30px
is a default height chosen to work well within
-the heights of most table rows.
Other image addition functions: ggplot_image
,
- test_image
, web_image
-# Create a tibble that contains heights -# of an image in pixels (one column as a -# string, the other as numerical values), -# then, create a gt table; use the -# `text_transform()` function to insert -# a local test image (PNG) image with the -# various sizes -tab_1 <- - dplyr::tibble( - pixels = px(seq(10, 35, 5)), - image = seq(10, 35, 5) - ) %>% - gt() %>% - text_transform( - locations = cells_data(vars(image)), - fn = function(x) { - local_image( - file = test_image(type = "png"), - height = as.numeric(x) - ) - } - )
R/helpers.R
- location_cells.Rd
These helper functions are used to target individual cells in different
-locations (e.g., the stub, the column labels, the title, etc.). They can be
-used in any of these functions (which all have a locations
argument):
-tab_footnote()
, tab_style()
, and
-text_transform()
Furthermore, multiple locations can be
-targeted by enclosing several cells_*()
helper functions in a list.
cells_title(groups = c("title", "subtitle")) - -cells_column_labels(columns, groups) - -cells_group(groups) - -cells_stub(rows = NULL) - -cells_data(columns = NULL, rows = NULL) - -cells_summary(groups = NULL, columns = NULL, rows = NULL)- -
columns, rows, groups | -either a vector of names, a vector of
-indices, values provided by |
-
---|
a list object of class location_cells
.
The following helper functions can be used to target cells (roughly in order -from the top to the bottom of a table):
-cells_title()
: targets the table title or the table subtitle
-depending on the value given to the groups
argument ("title"
or
-"subtitle"
).
cells_column_labels()
: targets labels in the column labels (the
-columns
argument) or the spanner column labels (the groups
-argument) in the table's column labels part.
cells_group()
: targets the row group labels in any available
-row groups using the groups
argument.
cells_stub()
: targets row labels in the table stub using the
-rows
argument.
cells_data()
: targets data cells in the table field using
-intersections of columns
and rows
.
cells_summary()
: targets summary cells in the table field using
-the groups
argument and intersections of columns
and
-rows
.
-# Use `sp500` to create a gt table; add -# a header (with a title and a subtitle), -# and then add a footnote to the subtitle -# with `tab_footnote()` and `cells_title()` -# in `locations` -tab_1 <- - sp500 %>% - dplyr::filter( - date >= "2015-01-05" & - date <="2015-01-10" - ) %>% - dplyr::select( - -c(adj_close, volume, high, low) - ) %>% - gt() %>% - tab_header( - title = "S&P 500", - subtitle = "Open and Close Values" - ) %>% - tab_footnote( - footnote = "All values in USD.", - locations = cells_title( - groups = "subtitle") - ) - -# Use `sza` to create a gt table; add a -# header and then add footnotes to the -# column labels with `tab_footnote()` and -# `cells_column_labels()` in `locations` -tab_2 <- - sza %>% - dplyr::filter( - latitude == 20 & month == "jan" & - !is.na(sza) - ) %>% - dplyr::select(-latitude, -month) %>% - gt() %>% - tab_footnote( - footnote = "True solar time.", - locations = cells_column_labels( - columns = vars(tst)) - ) %>% - tab_footnote( - footnote = "Solar zenith angle.", - locations = cells_column_labels( - columns = vars(sza)) - ) - -# Use `pizzaplace` to create a gt table -# with grouped data; add a summary with the -# `summary_rows()` function and then add a -# footnote to the "peppr_salami" row group -# label with `tab_footnote()` and with -# `cells_group()` in `locations` -tab_3 <- - pizzaplace %>% - dplyr::filter( - name %in% c("soppressata", "peppr_salami") - ) %>% - dplyr::group_by(name, size) %>% - dplyr::summarize( - `Pizzas Sold` = n() - ) %>% - gt(rowname_col = "size") %>% - summary_rows( - groups = TRUE, - columns = vars("Pizzas Sold"), - fns = list(TOTAL = "sum"), - formatter = fmt_number, - decimals = 0, - use_seps = TRUE - ) %>% - tab_footnote( - footnote = "The Pepper-Salami.", - cells_group(groups = "peppr_salami") - ) - -# Use `sza` to create a gt table; color -# all of the `month` values in the table -# stub with `tab_style()`, using `cells_stub()` -# in `locations` (`rows = TRUE` targets -# all stub rows) -tab_4 <- - sza %>% - dplyr::filter( - latitude == 20 & tst <= "1000") %>% - dplyr::select(-latitude) %>% - dplyr::filter(!is.na(sza)) %>% - tidyr::spread(key = "tst", value = sza) %>% - gt(rowname_col = "month") %>% - fmt_missing( - columns = TRUE, - missing_text = "" - ) %>% - tab_style( - style = cells_styles( - bkgd_color = "darkblue", - text_color = "white"), - locations = cells_stub(rows = TRUE) - ) - -# Use `gtcars` to create a gt table; add -# a footnote that targets a single data cell -# with `tab_footnote()`, using `cells_data()` -# in `locations` (`rows = hp == max(hp)` will -# target a single row in the `hp` column) -tab_5 <- - gtcars %>% - dplyr::filter(ctry_origin == "United Kingdom") %>% - dplyr::select(mfr, model, year, hp) %>% - gt() %>% - tab_options(footnote.glyph = "*") %>% - tab_footnote( - footnote = "Highest horsepower.", - locations = cells_data( - columns = vars(hp), - rows = hp == max(hp)) - ) - -# Use `countrypops` to create a gt table; add -# some styling to the summary data cells with -# with `tab_style()`, using `cells_summary()` -# in `locations` -tab_6 <- - countrypops %>% - dplyr::filter( - country_name == "Japan", - year < 1970) %>% - dplyr::select(-contains("country")) %>% - dplyr::mutate( - decade = paste0(substr(year, 1, 3), "0s") - ) %>% - dplyr::group_by(decade) %>% - gt( - rowname_col = "year", - groupname_col = "decade" - ) %>% - fmt_number( - columns = vars(population), - decimals = 0 - ) %>% - summary_rows( - groups = "1960s", - columns = vars(population), - fns = list("min", "max"), - formatter = fmt_number, - decimals = 0 - ) %>% - tab_style( - style = cells_styles( - text_style = "italic", - bkgd_color = "lightblue"), - locations = cells_summary( - groups = "1960s", - columns = vars(population), - rows = 1) - ) %>% - tab_style( - style = cells_styles( - text_style = "italic", - bkgd_color = "lightgreen"), - locations = cells_summary( - groups = "1960s", - columns = vars(population), - rows = 2) - )
Interpret input text as Markdown-formatted text
- -md(text)- -
text | -the text that is understood to contain Markdown formatting. |
-
---|
a character object that is tagged for a Markdown-to-HTML - transformation.
-a character object of class from_markdown
.
Other helper functions: cells_styles
,
- escape_latex
,
- gt_latex_dependencies
, html
,
- pct
, px
-# Use `exibble` to create a gt table; -# when adding a title, use the `md()` -# helper to use Markdown formatting -tab_1 <- - exibble %>% - dplyr::select(currency, char) %>% - gt() %>% - tab_header( - title = md("Using *Markdown*"))
Helper for providing a numeric value as percentage
- -pct(x)- -
x | -the numeric value to format as a string percentage for some
- |
-
---|
Other helper functions: cells_styles
,
- escape_latex
,
- gt_latex_dependencies
, html
,
- md
, px
See magrittr::%>%
for details.
lhs %>% rhs- - -
A synthetic dataset that describes pizza sales for a pizza place somewhere in
-the US. While the contents are artificial, the ingredients used to make the
-pizzas are far from it. There are 32 different pizzas that fall into 4
-different categories: classic
(classic pizzas: 'You probably had one
-like it before, but never like this!'), chicken
(pizzas with chicken
-as a major ingredient: 'Try the Southwest Chicken Pizza! You'll love it!'),
-supreme
(pizzas that try a little harder: 'My Soppressata pizza uses
-only the finest salami from my personal salumist!'), and, veggie
-(pizzas without any meats whatsoever: 'My Five Cheese pizza has so many
-cheeses, I can only offer it in Large Size!').
pizzaplace
-
- A tibble with 49574 rows and 7 variables:
The ID for the order, which consists of one or more pizzas
- at a give date
and time
A character representation of the order
date,
- expressed in the ISO 8601 date format (YYYY-MM-DD)
A character representation of the order
time,
- expressed as a 24-hour time the ISO 8601 extended time format
- (hh:mm:ss)
The short name for the pizza
The size of the pizza, which can either be S
,
- M
, L
, XL
(rare!), or XXL
(even rarer!);
- most pizzas are available in the S
, M
, and L
sizes
- but exceptions apply
The category or type of pizza, which can either be
- classic
, chicken
, supreme
, or veggie
The price of the pizza and the amount that it sold for - (in USD)
Each pizza in the dataset is identified by a short name
. The following
-listings provide the full names of each pizza and their main ingredients.
Classic Pizzas:
classic_dlx
: The Classic Deluxe Pizza (Pepperoni, Mushrooms, Red
-Onions, Red Peppers, Bacon)
big_meat
: The Big Meat Pizza (Bacon, Pepperoni, Italian Sausage,
-Chorizo Sausage)
pepperoni
: The Pepperoni Pizza (Mozzarella Cheese, Pepperoni)
hawaiian
: The Hawaiian Pizza (Sliced Ham, Pineapple, Mozzarella
-Cheese)
pep_msh_pep
: The Pepperoni, Mushroom, and Peppers Pizza
-(Pepperoni, Mushrooms, and Green Peppers)
ital_cpcllo
: The Italian Capocollo Pizza (Capocollo, Red
-Peppers, Tomatoes, Goat Cheese, Garlic, Oregano)
napolitana
: The Napolitana Pizza (Tomatoes, Anchovies, Green
-Olives, Red Onions, Garlic)
the_greek
: The Greek Pizza (Kalamata Olives, Feta Cheese,
-Tomatoes, Garlic, Beef Chuck Roast, Red Onions)
Chicken Pizzas:
thai_ckn
: The Thai Chicken Pizza (Chicken, Pineapple, Tomatoes,
-Red Peppers, Thai Sweet Chilli Sauce)
bbq_ckn
: The Barbecue Chicken Pizza (Barbecued Chicken, Red
-Peppers, Green Peppers, Tomatoes, Red Onions, Barbecue Sauce)
southw_ckn
: The Southwest Chicken Pizza (Chicken, Tomatoes, Red
-Peppers, Red Onions, Jalapeno Peppers, Corn, Cilantro, Chipotle Sauce)
cali_ckn
: The California Chicken Pizza (Chicken, Artichoke,
-Spinach, Garlic, JalapeƱo Peppers, Fontina Cheese, Gouda Cheese)
ckn_pesto
: The Chicken Pesto Pizza (Chicken, Tomatoes, Red
-Peppers, Spinach, Garlic, Pesto Sauce)
ckn_alfredo
: The Chicken Alfredo Pizza (Chicken, Red Onions,
-Red Peppers, Mushrooms, Asiago Cheese, Alfredo Sauce)
Supreme Pizzas:
brie_carre
: The Brie Carre Pizza (Brie Carre Cheese, Prosciutto,
- Caramelized Onions, Pears, Thyme, Garlic)
calabrese
: The Calabrese Pizza (āNduja Salami, Pancetta,
-Tomatoes, Red Onions, Friggitello Peppers, Garlic)
soppressata
: The Soppressata Pizza (Soppressata Salami, Fontina
-Cheese, Mozzarella Cheese, Mushrooms, Garlic)
sicilian
: The Sicilian Pizza (Coarse Sicilian Salami, Tomatoes,
-Green Olives, Luganega Sausage, Onions, Garlic)
ital_supr
: The Italian Supreme Pizza (Calabrese Salami,
-Capocollo, Tomatoes, Red Onions, Green Olives, Garlic)
peppr_salami
: The Pepper Salami Pizza (Genoa Salami, Capocollo,
-Pepperoni, Tomatoes, Asiago Cheese, Garlic)
prsc_argla
: The Prosciutto and Arugula Pizza (Prosciutto di San
-Daniele, Arugula, Mozzarella Cheese)
spinach_supr
: The Spinach Supreme Pizza (Spinach, Red Onions,
-Pepperoni, Tomatoes, Artichokes, Kalamata Olives, Garlic, Asiago Cheese)
spicy_ital
: The Spicy Italian Pizza (Capocollo, Tomatoes, Goat
-Cheese, Artichokes, Peperoncini verdi, Garlic)
Vegetable Pizzas
mexicana
: The Mexicana Pizza (Tomatoes, Red Peppers, Jalapeno
-Peppers, Red Onions, Cilantro, Corn, Chipotle Sauce, Garlic)
four_cheese
: The Four Cheese Pizza (Ricotta Cheese, Gorgonzola
-Piccante Cheese, Mozzarella Cheese, Parmigiano Reggiano Cheese, Garlic)
five_cheese
: The Five Cheese Pizza (Mozzarella Cheese, Provolone
-Cheese, Smoked Gouda Cheese, Romano Cheese, Blue Cheese, Garlic)
spin_pesto
: The Spinach Pesto Pizza (Spinach, Artichokes,
-Tomatoes, Sun-dried Tomatoes, Garlic, Pesto Sauce)
veggie_veg
: The Vegetables + Vegetables Pizza (Mushrooms,
-Tomatoes, Red Peppers, Green Peppers, Red Onions, Zucchini, Spinach, Garlic)
green_garden
: The Green Garden Pizza (Spinach, Mushrooms,
-Tomatoes, Green Olives, Feta Cheese)
mediterraneo
: The Mediterranean Pizza (Spinach, Artichokes,
-Kalamata Olives, Sun-dried Tomatoes, Feta Cheese, Plum Tomatoes, Red Onions)
spinach_fet
: The Spinach and Feta Pizza (Spinach, Mushrooms,
-Red Onions, Feta Cheese, Garlic)
ital_veggie
: The Italian Vegetables Pizza (Eggplant, Artichokes,
-Tomatoes, Zucchini, Red Peppers, Garlic, Pesto Sauce)
-#> Observations: 49,574 -#> Variables: 7 -#> $ id <chr> "2015-000001", "2015-000002", "2015-000002", "2015-000002", "20ā¦ -#> $ date <chr> "2015-01-01", "2015-01-01", "2015-01-01", "2015-01-01", "2015-0ā¦ -#> $ time <chr> "11:38:36", "11:57:40", "11:57:40", "11:57:40", "11:57:40", "11ā¦ -#> $ name <chr> "hawaiian", "classic_dlx", "mexicana", "thai_ckn", "five_cheeseā¦ -#> $ size <chr> "M", "M", "M", "L", "L", "L", "L", "M", "M", "M", "S", "S", "S"ā¦ -#> $ type <chr> "classic", "classic", "veggie", "chicken", "veggie", "supreme",ā¦ -#> $ price <dbl> 13.25, 16.00, 16.00, 20.75, 18.50, 20.75, 20.75, 16.50, 16.50, ā¦
This facilitates printing of the HTML table to the R console.
- -# S3 method for gt_tbl -print(x, ..., view = interactive())- -
x | -an object of class |
-
---|
Helper for providing a numeric value as pixels value
- -px(x)- -
x | -the numeric value to format as a string (e.g., |
-
---|
Other helper functions: cells_styles
,
- escape_latex
,
- gt_latex_dependencies
, html
,
- md
, pct
These objects are imported from other packages. Follow the links -below to see their documentation.
-starts_with
, ends_with
, contains
, matches
, one_of
, everything
A gt display table render function for use in Shiny
- -render_gt(expr, env = parent.frame(), quoted = FALSE, - outputArgs = list())- -
expr | -an expression that creates a gt table object. |
-
---|---|
env | -the environment in which to evaluate the |
-
quoted | -is expr a quoted expression (with |
-
outputArgs | -A list of arguments to be passed through to the implicit
-call to |
-
We can modify the display order of any row groups in a gt object with
-the row_group_order()
function. The groups
argument can either
-take a vector of row group names or a numeric vector of row group indices;
-whichever is provided, the row groups will adhere to this revised ordering.
-It isn't necessary to provide all row group names in groups
, rather,
-what is provided will assume the specified ordering at the top of the table
-and the remaining row groups will follow in their original ordering.
row_group_order(data, groups)- -
data | -a table object that is created using the |
-
---|---|
groups | -a vector of row group names, or, a numeric vector of indices -corresponding to the new ordering. Either vector must correspond to -assigned group names or the index positions. Also, either type of vector is -not required to have all of the row group names or available index -positions within it; any omitted values will be added to the end while -preserving the original ordering. |
-
an object of class gt_tbl
.
-# Use `exibble` to create a gt table -# with a stub and with row groups; -# modify the order of the row groups -# with `row_group_order()`, specifying -# the new ordering in `groups` -tab_1 <- - exibble %>% - dplyr::select(char, currency, row, group) %>% - gt( - rowname_col = "row", - groupname_col = "group" - ) %>% - row_group_order( - groups = c("grp_b", "grp_a") - )
This dataset provides daily price indicators for the S&P 500 index from the -beginning of 1950 to the end of 2015. The index includes 500 leading -companies and captures about 80% coverage of available market capitalization.
- -sp500
-
- A tibble with 16607 rows and 7 variables:
The date expressed as Date
values
The day's opening, high, low, and closing
- prices in USD; the close
price is adjusted for splits
the number of trades for the given date
The close price adjusted for both dividends and splits
Data collected from https://finance.yahoo.com/quote/%5EGSPC/history/.
- - --#> Observations: 16,607 -#> Variables: 7 -#> $ date <date> 2015-12-31, 2015-12-30, 2015-12-29, 2015-12-28, 2015-12-24ā¦ -#> $ open <dbl> 2060.59, 2077.34, 2060.54, 2057.77, 2063.52, 2042.20, 2023.ā¦ -#> $ high <dbl> 2062.54, 2077.34, 2081.56, 2057.77, 2067.36, 2064.73, 2042.ā¦ -#> $ low <dbl> 2043.62, 2061.97, 2060.54, 2044.20, 2058.73, 2042.20, 2020.ā¦ -#> $ close <dbl> 2043.94, 2063.36, 2078.36, 2056.50, 2060.99, 2064.29, 2038.ā¦ -#> $ volume <dbl> 2655330000, 2367430000, 2542000000, 2492510000, 1411860000,ā¦ -#> $ adj_close <dbl> 2043.94, 2063.36, 2078.36, 2056.50, 2060.99, 2064.29, 2038.ā¦
Add summary rows to one or more row groups by using the input data already
-provided in the gt()
function alongside any suitable
-aggregation functions. Should we need to obtain the summary data for external
-purposes, the extract_summary()
can be used with a
-gt_tbl
object where summary rows were added via summary_rows()
.
summary_rows(data, groups = NULL, columns = NULL, fns, - missing_text = "---", formatter = fmt_number, ...)- -
data | -a table object that is created using the |
-
---|---|
groups | -the row groups labels that identify which summary rows will be -added. |
-
columns | -the columns for which the summaries should be calculated. If -nothing is provided, then the supplied aggregation functions will be -applied to all columns. |
-
fns | -functions used for aggregations. This can include base functions
-like |
-
missing_text | -the text to be used in place of |
-
formatter | -a formatter function name. These can be any of the
- |
-
... | -values passed to the |
-
an object of class gt_tbl
.
-# Use `sp500` to create a gt table with -# row groups; create summary rows (`min`, -# `max`, `avg`) by row group, where each -# each row group is a week number -tab_1 <- - sp500 %>% - dplyr::filter( - date >= "2015-01-05" & - date <="2015-01-16" - ) %>% - dplyr::arrange(date) %>% - dplyr::mutate( - week = paste0( - "W", strftime(date, format = "%V")) - ) %>% - dplyr::select(-adj_close, -volume) %>% - gt( - rowname_col = "date", - groupname_col = "week" - ) %>% - summary_rows( - groups = TRUE, - columns = vars(open, high, low, close), - fns = list( - min = ~min(.), - max = ~max(.), - avg = ~mean(.)), - formatter = fmt_number, - use_seps = FALSE - )
This dataset contains solar zenith angles (in degrees, with the range of -0-90) every half hour from 04:00 to 12:00, true solar time. This set of -values is calculated on the first of every month for 4 different northern -hemisphere latitudes. For determination of afternoon values, the presented -tabulated values are symmetric about noon.
- -sza
-
- A tibble with 816 rows and 4 variables:
The latitude in decimal degrees for the observations
The measurement month; all calculations where conducted - for the first day of each month
The true solar time at the given latitude
and date
- (first of month
) for which the solar zenith angle is calculated
The solar zenith angle in degrees, where NA
s
- indicate that sunrise hadn't yet occurred by the tst
value
Calculated Actinic Fluxes (290 - 700 nm) for Air Pollution -Photochemistry Applications (Peterson, 1976), available at: -https://nepis.epa.gov/Exe/ZyPURL.cgi?Dockey=9100JA26.txt.
- -The solar zenith angle (SZA) is one measure that helps to describe the sun's -path across the sky. It's defined as the angle of the sun relative to a line -perpendicular to the earth's surface. It is useful to calculate the SZA in -relation to the true solar time. True solar time relates to the position of -the sun with respect to the observer, which is different depending on the -exact longitude. For example, two hours before the sun crosses the meridian -(the highest point it would reach that day) corresponds to a true solar time -of 10 a.m. The SZA has a strong dependence on the observer's latitude. For -example, at a latitude of 50 degrees N at the start of January, the noontime -SZA is 73.0 but a different observer at 20 degrees N would measure the -noontime SZA to be 43.0 degrees.
- - --#> Observations: 816 -#> Variables: 4 -#> $ latitude <dbl> 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, ā¦ -#> $ month <fct> jan, jan, jan, jan, jan, jan, jan, jan, jan, jan, jan, jan, ā¦ -#> $ tst <chr> "0400", "0430", "0500", "0530", "0600", "0630", "0700", "073ā¦ -#> $ sza <dbl> NA, NA, NA, NA, NA, NA, 84.9, 78.7, 72.7, 66.1, 61.5, 56.5, ā¦
The tab_footnote()
function can make it a painless process to add a
-footnote to a gt table. There are two components to a footnote: (1) a
-glyph that is attached to the targeted cell text, and (2) the footnote text
-(that starts with the corresponding glyph) that is placed in the table's
-footer area. Each call of tab_footnote()
will add a different note,
-and one or more cells can be targeted via the location helper functions
-(e.g., cells_data()
, cells_column_labels()
,
-etc.).
tab_footnote(data, footnote, locations)- -
data | -a table object that is created using the |
-
---|---|
footnote | -the text to be used in the footnote. We can optionally use
-the |
-
locations | -the cell or set of cells to be associated with the footnote.
-Supplying any of the |
-
an object of class gt_tbl
.
The formatting of the footnotes can be controlled through the use of various
-parameters in the tab_options()
function:
footnote.sep
: allows for a choice of the separator between
-consecutive footnotes in the table footer. By default, this is set to a
-linebreak.
footnote.glyph
: the set of sequential characters or numbers
-used to identify the footnotes.
footnote.font.size
: the size of the font used in the footnote
-section.
footnote.padding
: the amount of padding to apply between the
-footnote and source note sections in the table footer.
Other table-part creation/modification functions: gt_preview
,
- gt
, tab_header
,
- tab_options
, tab_row_group
,
- tab_source_note
, tab_spanner
,
- tab_stubhead_label
, tab_style
-# Use `sza` to create a gt table; color -# the `sza` column using the `data_color()` -# function, then, add a footnote to the -# `sza` column label explaining what the -# color scale signifies -tab_1 <- - sza %>% - dplyr::filter( - latitude == 20 & - month == "jan" & - !is.na(sza) - ) %>% - dplyr::select(-latitude, -month) %>% - gt() %>% - data_color( - columns = vars(sza), - colors = scales::col_numeric( - palette = c("white", "yellow", "navyblue"), - domain = c(0, 90)) - ) %>% - tab_footnote( - footnote = "Color indicates height of sun.", - locations = cells_column_labels( - columns = vars(sza)) - )
We can add a table header to the gt table with a title and even a -subtitle. A table header is an optional table part that is positioned above -the column labels. We have the flexibility to use Markdown formatting for the -header's title and subtitle. Furthermore, if the table is intended for HTML -output, we can use HTML in either of the title or subtitle.
- -tab_header(data, title, subtitle = NULL)- -
data | -a table object that is created using the |
-
---|---|
title, subtitle | -text to be used in the table title and, optionally, for
-the table subtitle. We can elect to use the |
-
an object of class gt_tbl
.
Other table-part creation/modification functions: gt_preview
,
- gt
, tab_footnote
,
- tab_options
, tab_row_group
,
- tab_source_note
, tab_spanner
,
- tab_stubhead_label
, tab_style
-
Modify the options available in a table. These options are named by the -components, the subcomponents, and the element that can adjusted.
- -tab_options(data, table.width = NULL, table.font.size = NULL, - table.background.color = NULL, table.border.top.style = NULL, - table.border.top.width = NULL, table.border.top.color = NULL, - heading.background.color = NULL, heading.title.font.size = NULL, - heading.subtitle.font.size = NULL, - heading.border.bottom.style = NULL, - heading.border.bottom.width = NULL, - heading.border.bottom.color = NULL, - column_labels.background.color = NULL, - column_labels.font.size = NULL, column_labels.font.weight = NULL, - stub_group.background.color = NULL, stub_group.font.size = NULL, - stub_group.font.weight = NULL, stub_group.border.top.style = NULL, - stub_group.border.top.width = NULL, - stub_group.border.top.color = NULL, - stub_group.border.bottom.style = NULL, - stub_group.border.bottom.width = NULL, - stub_group.border.bottom.color = NULL, field.border.top.style = NULL, - field.border.top.width = NULL, field.border.top.color = NULL, - field.border.bottom.style = NULL, field.border.bottom.width = NULL, - field.border.bottom.color = NULL, row.padding = NULL, - summary_row.background.color = NULL, summary_row.padding = NULL, - summary_row.text_transform = NULL, footnote.sep = NULL, - footnote.glyph = NULL, footnote.font.size = NULL, - footnote.padding = NULL, sourcenote.font.size = NULL, - sourcenote.padding = NULL, row.striping.include_stub = NULL, - row.striping.include_field = NULL)- -
data | -a table object that is created using the |
-
---|---|
table.width | -the width of the table. Can be specified as a
-single-length character with units of pixels or as a percentage. If
-provided as a single-length numeric vector, it is assumed that the value is
-given in units of pixels. The |
-
table.font.size, heading.title.font.size, heading.subtitle.font.size, column_labels.font.size, stub_group.font.size, footnote.font.size, sourcenote.font.size | -font sizes for the parent text element |
-
table.background.color, heading.background.color, column_labels.background.color, stub_group.background.color, summary_row.background.color | -background colors for the parent element |
-
table.border.top.style, table.border.top.width, table.border.top.color | -the style, width, and color of the table's top border. |
-
heading.border.bottom.style, heading.border.bottom.width, heading.border.bottom.color | -the style, width, and color of the heading's bottom border. |
-
column_labels.font.weight, stub_group.font.weight | -the font weight of the
- |
-
stub_group.border.top.style, stub_group.border.top.width, stub_group.border.top.color | -the style, width, and color of the stub heading's top border. |
-
stub_group.border.bottom.style, stub_group.border.bottom.width, stub_group.border.bottom.color | -the style, width, and color of the stub heading's bottom border. |
-
field.border.top.style, field.border.top.width, field.border.top.color | -the style, width, and color of the field's top border. |
-
field.border.bottom.style, field.border.bottom.width, field.border.bottom.color | -the style, width, and color of the field's bottom border. |
-
row.padding, summary_row.padding | -the amount of padding in each row and -in each summary row. |
-
summary_row.text_transform | -an option to apply text transformations to -the label text in each summary row. |
-
footnote.sep | -the separating characters between adjacent footnotes in -the footnotes section. The default value produces a linebreak. |
-
footnote.glyph | -the set of sequential figures or characters used to
-identify the footnotes. We can either supply the keyword |
-
footnote.padding, sourcenote.padding | -the amount of padding to apply to -the footnote and source note sections. |
-
row.striping.include_stub | -an option for whether to include the stub -when striping rows. |
-
row.striping.include_field | -an option for whether to include the field -when striping rows. |
-
an object of class gt_tbl
.
Other table-part creation/modification functions: gt_preview
,
- gt
, tab_footnote
,
- tab_header
, tab_row_group
,
- tab_source_note
, tab_spanner
,
- tab_stubhead_label
, tab_style
-# Use `exibble` to create a gt table with -# all the main parts added; we can use this -# going forward to demo some `tab_options()` -tab_1 <- - exibble %>% - dplyr::select( - -c(fctr, date, time, datetime) - ) %>% - gt( - rowname_col = "row", - groupname_col = "group" - ) %>% - tab_header( - title = md("Data listing from **exibble**"), - subtitle = md("`exibble` is an R dataset") - ) %>% - fmt_number(columns = vars(num)) %>% - fmt_currency(columns = vars(currency)) %>% - tab_footnote( - footnote = "Using commas for separators.", - locations = cells_data( - columns = vars(num), - rows = num > 1000) - ) %>% - tab_footnote( - footnote = "Using commas for separators.", - locations = cells_data( - columns = vars(currency), - rows = currency > 1000) - ) %>% - tab_footnote( - footnote = "Alphabetical fruit.", - locations = cells_column_labels( - columns = vars(char)) - ) - -# Modify the table width to 100% (which -# spans the entire content width area) -tab_2 <- - tab_1 %>% - tab_options( - table.width = pct(100) - ) - -# Modify the table's background color -# to be "lightcyan" -tab_3 <- - tab_1 %>% - tab_options( - table.background.color = "lightcyan" - ) - -# Use letters as the glyphs for footnote -# references; also, separate footnotes in -# the footer by spaces instead of newlines -tab_4 <- - tab_1 %>% - tab_options( - footnote.sep = " ", - footnote.glyph = letters - ) - -# Change the padding of data rows to 5px -tab_5 <- - tab_1 %>% - tab_options( - row.padding = px(5) - ) - -# Reduce the size of the title and the -# subtitle text -tab_6 <- - tab_1 %>% - tab_options( - heading.title.font.size = "small", - heading.subtitle.font.size = "small" - )
Create a row group with a collection of rows. This requires specification of
-the rows to be included, either by supplying row labels, row indices, or
-through use of a select helper function like starts_with()
.
tab_row_group(data, group = NULL, rows = NULL, others = NULL)- -
data | -a table object that is created using the |
-
---|---|
group | -the name of the row group. This text will also serve as the row -group label. |
-
rows | -the rows to be made components of the row group. Can either be a
-vector of row captions provided |
-
others | -an option to set a default row group label for any rows not
-formally placed in a row group named by |
-
an object of class gt_tbl
.
Other table-part creation/modification functions: gt_preview
,
- gt
, tab_footnote
,
- tab_header
, tab_options
,
- tab_source_note
, tab_spanner
,
- tab_stubhead_label
, tab_style
-# Use `gtcars` to create a gt table and -# add two row groups with the labels: -# `numbered` and `NA` (a group without -# a title, or, the rest) -tab_1 <- - gtcars %>% - dplyr::select(model, year, hp, trq) %>% - dplyr::slice(1:8) %>% - gt(rowname_col = "model") %>% - tab_row_group( - group = "numbered", - rows = matches("^[0-9]") - ) - -# Use `gtcars` to create a gt table; -# add two row groups with the labels -# `powerful` and `super powerful`: the -# distinction being `hp` lesser or -# greater than `600` -tab_2 <- - gtcars %>% - dplyr::select(model, year, hp, trq) %>% - dplyr::slice(1:8) %>% - gt(rowname_col = "model") %>% - tab_row_group( - group = "powerful", - rows = hp <= 600 - ) %>% - tab_row_group( - group = "super powerful", - rows = hp > 600 - )
Add a source note to the footer part of the gt table. A source note is
-useful for citing the data included in the table. Several can be added to the
-footer, simply use multiple calls of tab_source_note()
and they will
-be inserted in the order provided. We can use Markdown formatting for the
-note, or, if the table is intended for HTML output, we can include HTML
-formatting.
tab_source_note(data, source_note)- -
data | -a table object that is created using the |
-
---|---|
source_note | -text to be used in the source note. We can optionally use
-the |
-
an object of class gt_tbl
.
Other table-part creation/modification functions: gt_preview
,
- gt
, tab_footnote
,
- tab_header
, tab_options
,
- tab_row_group
, tab_spanner
,
- tab_stubhead_label
, tab_style
-
Set a spanner column label by mapping it to columns already in the table. -This label is placed above one or more column labels, spanning the width of -those columns and column labels.
- -tab_spanner(data, label, columns)- -
data | -a table object that is created using the |
-
---|---|
label | -the text to use for the spanner column label. |
-
columns | -the columns to be components of the spanner heading. |
-
an object of class gt_tbl
.
Other table-part creation/modification functions: gt_preview
,
- gt
, tab_footnote
,
- tab_header
, tab_options
,
- tab_row_group
,
- tab_source_note
,
- tab_stubhead_label
, tab_style
-# Use `gtcars` to create a gt table; -# Group several columns related to car -# performance under a spanner column -# with the label `performance` -tab_1 <- - gtcars %>% - dplyr::select( - -mfr, -trim, bdy_style, drivetrain, - -drivetrain, -trsmn, -ctry_origin - ) %>% - dplyr::slice(1:8) %>% - gt(rowname_col = "model") %>% - tab_spanner( - label = "performance", - columns = vars( - hp, hp_rpm, trq, trq_rpm, - mpg_c, mpg_h) - )
Add a label to the stubhead of a gt table. The stubhead is the lone -element that is positioned left of the column labels, and above the stub. If -a stub does not exist, then there is no stubhead (so no change will be made -when using this function in that case). We have the flexibility to use -Markdown formatting for the stubhead label. Furthermore, if the table is -intended for HTML output, we can use HTML for the stubhead label.
- -tab_stubhead_label(data, label)- -
data | -a table object that is created using the |
-
---|---|
label | -the text to be used as the stubhead label We can optionally
-use the |
-
an object of class gt_tbl
.
Other table-part creation/modification functions: gt_preview
,
- gt
, tab_footnote
,
- tab_header
, tab_options
,
- tab_row_group
,
- tab_source_note
, tab_spanner
,
- tab_style
-
With the tab_style()
function we can target specific cells and apply
-styles to them. This is best done in conjunction with the
-cells_styles()
helper function. At present this function is
-focused on the application of styles for HTML output only (as such, other
-output formats will ignore all tab_style()
calls). With the help of
-cells_styles()
, we can set the following styles:
the background color of the cell (bkgd_color
)
the cell's text color (text_color
), font (text_font
), or
-size (text_size
)
the text style (text_style
), enabling the use of italics or
-oblique text.
text decoration (text_decorate
): use overlines, line-throughs,
-or underlines
text transformations (text_transform
) that result in lowercased,
-uppercased, or capitalized text
the text weight (text_weight
), allowing the use of thin to
-bold text (the degree of choice is greater with variable fonts)
the alignment of text (text_align
)
a stretching property for text that condenses or expands text
-(text_stretch
)
the text indentation (text_indent
)
tab_style(data, style, locations)- -
data | -a table object that is created using the |
-
---|---|
style | -a vector of styles to use. The |
-
locations | -the cell or set of cells to be associated with the style
-Supplying any of the |
-
an object of class gt_tbl
.
cells_styles()
as a helper for defining custom styles
- and cells_data()
as a useful helper function for targeting
- one or more data cells to be styled.
Other table-part creation/modification functions: gt_preview
,
- gt
, tab_footnote
,
- tab_header
, tab_options
,
- tab_row_group
,
- tab_source_note
, tab_spanner
,
- tab_stubhead_label
-# Use `exibble` to create a gt table; -# add styles that are to be applied -# to data cells that satisfy a -# condition (using `tab_style()`) -tab_1 <- - exibble %>% - dplyr::select(num, currency) %>% - gt() %>% - fmt_number( - columns = vars(num, currency), - decimals = 1 - ) %>% - tab_style( - style = cells_styles( - bkgd_color = "lightcyan", - text_weight = "bold"), - locations = cells_data( - columns = vars(num), - rows = num >= 5000) - ) %>% - tab_style( - style = cells_styles( - bkgd_color = "#F9E3D6", - text_style = "italic"), - locations = cells_data( - columns = vars(currency), - rows = currency < 100) - ) - -# Use `sp500` to create a gt table; -# color entire rows of cells based -# on values in a particular column -tab_2 <- - sp500 %>% - dplyr::filter( - date >= "2015-12-01" & - date <= "2015-12-15" - ) %>% - dplyr::select(-c(adj_close, volume)) %>% - dplyr::mutate(date = as.character(date)) %>% - gt() %>% - tab_style( - style = cells_styles( - bkgd_color = "lightgreen"), - locations = cells_data( - rows = close > open) - ) %>% - tab_style( - style = cells_styles( - bkgd_color = "crimson", - text_color = "white"), - locations = cells_data( - rows = open > close) - )
Two test images are available within the gt package. Both contain the
-same imagery (sized at 200px by 200px) but one is a PNG file while the other
-is an SVG file. This function is most useful when paired with
-local_image()
since we test various sizes of the test image
-within that function.
test_image(type = c("png", "svg"))- -
type | -the type of the image, which can either be |
-
---|
Other image addition functions: ggplot_image
,
- local_image
, web_image
R/text_transform.R
- text_transform.Rd
Perform targeted text transformation with a function
- -text_transform(data, locations, fn)- -
data | -a table object that is created using the |
-
---|---|
locations | -the cell or set of cells to be associated with the text
-transformation. Supplying any of the |
-
fn | -the function to use for text transformation. |
-
an object of class gt_tbl
.
Other data formatting functions: data_color
,
- fmt_currency
, fmt_datetime
,
- fmt_date
, fmt_missing
,
- fmt_number
, fmt_passthrough
,
- fmt_percent
, fmt_scientific
,
- fmt_time
, fmt
-# Use `exibble` to create a gt table; -# transform the formatted text in the -# `num` and `currency` columns using -# a function within `text_transform()`, -# where `x` is a formatted vector of -# column values -tab_1 <- - exibble %>% - dplyr::select(num, char, currency) %>% - dplyr::slice(1:4) %>% - gt() %>% - fmt_number(columns = vars(num)) %>% - fmt_currency(columns = vars(currency)) %>% - text_transform( - locations = cells_data( - columns = vars(num)), - fn = function(x) { - - paste0( - x, " (", - dplyr::case_when( - x > 20 ~ "large", - x <= 20 ~ "small"), - ")") - } - ) %>% - text_transform( - locations = cells_data( - columns = vars(currency)), - fn = function(x) { - - ifelse( - grepl(",", x), - gsub("\\.\\d\\d", "", x), - x) - } - )
We can flexibly add a web image inside of a table with web_image()
-function. The function provides a convenient way to generate an HTML fragment
-with an image URL. Because this function is currently HTML-based, it is only
-useful for HTML table output. To use this function inside of data cells, it
-is recommended that the text_transform()
function is used. With
-that function, we can specify which data cells to target and then include a
-web_image()
call within the required user-defined function (for the
-fn
argument). If we want to include an image in other places (e.g., in
-the header, within footnote text, etc.) we need to use web_image()
-within the html()
helper function.
web_image(url, height = 30)- -
url | -a url that resolves to an image file. |
-
---|---|
height | -the absolute height (px) of the image in the table cell. |
-
a character object with an HTML fragment that can be placed inside of - a cell.
- -By itself, the function creates an HTML image tag, so, the call
-web_image("http://some.web.site/image.png")
evaluates to:
<img src=\"http://some.web.site/image.png\" style=\"height:30px;\">
where a height of 30px
is a default height chosen to work well within
-the heights of most table rows.
Other image addition functions: ggplot_image
,
- local_image
, test_image
-# Get the PNG-based logo for the R -# Project from an image URL -r_png_url <- - "https://www.r-project.org/logo/Rlogo.png" - -# Create a tibble that contains heights -# of an image in pixels (one column as a -# string, the other as numerical values), -# then, create a gt table; use the -# `text_transform()` function to insert -# the R logo PNG image with the various -# sizes -tab_1 <- - dplyr::tibble( - pixels = px(seq(10, 35, 5)), - image = seq(10, 35, 5) - ) %>% - gt() %>% - text_transform( - locations = cells_data(vars(image)), - fn = function(x) { - web_image( - url = r_png_url, - height = as.numeric(x) - ) - } - ) - -# Get the SVG-based logo for the R -# Project from an image URL -r_svg_url <- - "https://www.r-project.org/logo/Rlogo.svg" - -# Create a tibble that contains heights -# of an image in pixels (one column as a -# string, the other as numerical values), -# then, create a gt table; use the -# `tab_header()` function to insert -# the R logo SVG image once in the title -# and five times in the subtitle -tab_2 <- - dplyr::tibble( - pixels = px(seq(10, 35, 5)), - image = seq(10, 35, 5) - ) %>% - gt() %>% - tab_header( - title = html( - web_image( - url = r_svg_url, - height = px(50) - ) - ), - subtitle = html( - web_image( - url = r_svg_url, - height = px(12) - ) %>% - rep(5) - ) - )