The formatters
package provides two core pieces of
functionality, both related to ASCII rendering:
format_value
provides the ability to format single- and
multi-valued elements into ASCII display-ready stringsmatrix_form
framework provides generics for
implementing ASCII rendering support for display tablesBoth of these feature sets are used in the rtables
package.
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.
formatters
is available on CRAN and you can install the
latest released version with:
install.packages("formatters")
or you can install the latest development version directly from GitHub with:
# install.packages("pak")
::pak("insightsengineering/formatters") pak
Packaged releases (both those on CRAN and those between official CRAN releases) can be found in the releases list.
To understand how to use this package, please refer to the Introduction
to formatters
article, which provides multiple examples
of code implementation.
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:
list_valid_format_labels()
$`1d`
1] "xx" "xx." "xx.x"
[4] "xx.xx" "xx.xxx" "xx.xxxx"
[7] "xx%" "xx.%" "xx.x%"
[10] "xx.xx%" "xx.xxx%" "(N=xx)"
[13] ">999.9" ">999.99" "x.xxxx | (<0.0001)"
[
$`2d`
1] "xx / xx" "xx. / xx." "xx.x / xx.x"
[4] "xx.xx / xx.xx" "xx.xxx / xx.xxx" "xx (xx%)"
[7] "xx (xx.%)" "xx (xx.x%)" "xx (xx.xx%)"
[10] "xx. (xx.%)" "xx.x (xx.x%)" "xx.xx (xx.xx%)"
[13] "(xx, xx)" "(xx., xx.)" "(xx.x, xx.x)"
[16] "(xx.xx, xx.xx)" "(xx.xxx, xx.xxx)" "(xx.xxxx, xx.xxxx)"
[19] "xx - xx" "xx.x - xx.x" "xx.xx - xx.xx"
[22] "xx (xx)" "xx. (xx.)" "xx.x (xx.x)"
[25] "xx.xx (xx.xx)" "xx (xx.)" "xx (xx.x)"
[28] "xx (xx.xx)" "xx.x, xx.x" "xx.x to xx.x"
[
$`3d`
1] "xx.xx (xx.xx - xx.xx)"
[
attr(,"info")
1] "xx does not modify the element, and xx. rounds a number to 0 digits" [
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.
Values are formatted via calls to format_value
, like
so:
format_value(5.1235, format = "xx.xx")
1] "5.12"
[
format_value(c(1.2355, 2.6789), "(xx.xx, xx.xx)")
1] "(1.24, 2.68)" [
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:
## 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")
<- function(i, rnms) {
fake_pagdf_row <- rnms[i]
nm pagdfrow(nm = nm, lab = nm, rnum = i, pth = nm, extent = 1L,
rclass = "NA")
}
<- function(df) {
matrix_form.data.frame <- lapply(df, function(x) if(is.null(obj_format(x))) "xx" else obj_format(x))
fmts
<- mapply(function(x, fmt) {
bodystrs sapply(x, format_value, format = fmt)
x = df, fmt = fmts)
},
<- row.names(df)
rnms if(is.null(rnms))
<- as.character(seq_len(NROW(df)))
rnms
<- names(df)
cnms
<- rbind(c("", cnms),
strings cbind(rnms, bodystrs))
<- nrow(strings)
fnr <- ncol(strings)
fnc
## center alignment for column labels, left alignment for everything else
<- rbind("center",
aligns matrix("left", nrow = NROW(df), ncol = fnc))
## build up fake pagination df,
<- basic_pagdf(row.names(df))
rowdf MatrixPrintForm(strings = strings,
aligns = aligns,
spans = matrix(1, nrow = fnr, ncol = fnc),
formats = NULL,
row_info = rowdf,
has_topleft = FALSE,
nlines_header = 1,
nrow_header = 1)
}cat(toString(matrix_form.data.frame(mtcars)))
mpg cyl disp hp drat wt qsec vs am gear carb
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ21 6 160 110 3.9 2.62 16.46 0 1 4 4
Mazda RX4 21 6 160 110 3.9 2.875 17.02 0 1 4 4
Mazda RX4 Wag 710 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1
Datsun 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
Hornet 18.7 8 360 175 3.15 3.44 17.02 0 0 3 2
Hornet Sportabout 18.1 6 225 105 2.76 3.46 20.22 1 0 3 1
Valiant 360 14.3 8 360 245 3.21 3.57 15.84 0 0 3 4
Duster 24.4 4 146.7 62 3.69 3.19 20 1 0 4 2
Merc 240D 230 22.8 4 140.8 95 3.92 3.15 22.9 1 0 4 2
Merc 280 19.2 6 167.6 123 3.92 3.44 18.3 1 0 4 4
Merc 17.8 6 167.6 123 3.92 3.44 18.9 1 0 4 4
Merc 280C 16.4 8 275.8 180 3.07 4.07 17.4 0 0 3 3
Merc 450SE 17.3 8 275.8 180 3.07 3.73 17.6 0 0 3 3
Merc 450SL 15.2 8 275.8 180 3.07 3.78 18 0 0 3 3
Merc 450SLC 10.4 8 472 205 2.93 5.25 17.98 0 0 3 4
Cadillac Fleetwood 10.4 8 460 215 3 5.424 17.82 0 0 3 4
Lincoln Continental 14.7 8 440 230 3.23 5.345 17.42 0 0 3 4
Chrysler Imperial 128 32.4 4 78.7 66 4.08 2.2 19.47 1 1 4 1
Fiat 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
Honda Civic 33.9 4 71.1 65 4.22 1.835 19.9 1 1 4 1
Toyota Corolla 21.5 4 120.1 97 3.7 2.465 20.01 1 0 3 1
Toyota Corona 15.5 8 318 150 2.76 3.52 16.87 0 0 3 2
Dodge Challenger 15.2 8 304 150 3.15 3.435 17.3 0 0 3 2
AMC Javelin 13.3 8 350 245 3.73 3.84 15.41 0 0 3 4
Camaro Z28 19.2 8 400 175 3.08 3.845 17.05 0 0 3 2
Pontiac Firebird -9 27.3 4 79 66 4.08 1.935 18.9 1 1 4 1
Fiat X1914-2 26 4 120.3 91 4.43 2.14 16.7 0 1 5 2
Porsche 30.4 4 95.1 113 3.77 1.513 16.9 1 1 5 2
Lotus Europa 15.8 8 351 264 4.22 3.17 14.5 0 1 5 4
Ford Pantera L 19.7 6 145 175 3.62 2.77 15.5 0 1 5 6
Ferrari Dino 15 8 301 335 3.54 3.57 14.6 0 1 5 8
Maserati Bora 21.4 4 121 109 4.11 2.78 18.6 1 1 4 2 Volvo 142E