--- title: "Introduction to the formatters package" author: "Gabriel Becker" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Introduction to the formatters package} %\VignetteEncoding{UTF-8} %\VignetteEngine{knitr::rmarkdown} editor_options: chunk_output_type: console markdown: wrap: 72 --- ```{r, echo=FALSE} knitr::opts_chunk$set(comment = "") library(formatters) ``` # formatters The `formatters` package provides two core pieces of functionality, both related to ASCII rendering: 1. `format_value` provides the ability to format single- and multi-valued elements into ASCII display-ready strings 2. the `matrix_form` framework provides generics for implementing ASCII rendering support for display tables **Both of these feature sets are used in the `rtables` package.** # Formatting values The core motivation for `formatters` is the rendering of reporting tables into ASCII. In this context a 'value' is the raw content that to appear in a single table cell. Most commonly this is a numeric vector of length 1, 2 or -- occasionally -- 3. ## Format labels `formatters` ships with a large number of pre-defined formats appropriate for rendering values into ASCII strings. These existing formats are specified by their labels. We can see the list of these by calling the `list_valid_format_labels` function: ```{r} list_valid_format_labels() ``` Each of these labels describes how the incoming (possibly multi-element) raw value will be formatted. `xx` indicates that an element of the value will be printed as is, with no modification. `xx.` indicates that a numeric value element will be rounded to 0 decimal places, `xx.x` indicates rounding to 1 decimal place, etc. ## Formatting values Values are formatted via calls to `format_value`, like so: ```{r} format_value(5.1235, format = "xx.xx") ``` ```{r} format_value(c(1.2355, 2.6789), "(xx.xx, xx.xx)") ``` # Table Rendering Framework **Advanced Usage Only** These features are supported, and in fact are used in `rtables` and the experimental `rlistings`. That said, the API is currently very low-level and tailored to what `rtables` and `rlistings` need. How useful this is to other table frameworks may vary. The second major piece of functionality in `formatters` is the ability to render tables into ASCII (and thus directly to the terminal) based on a so-called `MatrixPrintForm` representation of the table. To hook up `rtables`-style ASCII display for your tables, it suffices to export a method for the exported `matrix_form` generic `formatters` provides. This method must return a `MatrixPrintForm` object representing your table. We can build a baby example method for `data.frames` to illustrate this process: ```{r} ## pagdfrow supports a large number of pieces of information regarding ## siblings and what information should be repeated after a pagination. ## we ignore all that here and just give the absolutely crucial info: ## nm (name), lab (label), rnum (absolute row position), pth ("path"), ## extent (how many lines it takes up), rclass ("class of row") fake_pagdf_row <- function(i, rnms) { nm <- rnms[i] pagdfrow( nm = nm, lab = nm, rnum = i, pth = nm, extent = 1L, rclass = "NA" ) } matrix_form.data.frame <- function(df) { fmts <- lapply(df, function(x) if (is.null(obj_format(x))) "xx" else obj_format(x)) bodystrs <- mapply(function(x, fmt) { sapply(x, format_value, format = fmt) }, x = df, fmt = fmts) rnms <- row.names(df) if (is.null(rnms)) { rnms <- as.character(seq_len(NROW(df))) } cnms <- names(df) strings <- rbind( c("", cnms), cbind(rnms, bodystrs) ) fnr <- nrow(strings) fnc <- ncol(strings) ## center alignment for column labels, left alignment for everything else aligns <- rbind( "center", matrix("left", nrow = NROW(df), ncol = fnc) ) ## build up fake pagination df, rowdf <- basic_pagdf(row.names(df)) MatrixPrintForm( strings = strings, aligns = aligns, spans = matrix(1, nrow = fnr, ncol = fnc), formats = matrix("", nrow = fnr, ncol = fnc), row_info = rowdf, has_topleft = FALSE, nlines_header = 1, nrow_header = 1 ) } cat(toString(matrix_form.data.frame(mtcars))) ```