Tables so Beautifully Fine-Tuned You Will Believe It's Magic

The introduction of the 'broom' package has made converting model objects into data frames as simple as a single function. While the 'broom' package focuses on providing tidy data frames that can be used in advanced analysis, it deliberately stops short of providing functionality for reporting models in publication-ready tables. 'pixiedust' provides this functionality with a programming interface intended to be similar to 'ggplot2's system of layers with fine tuned control over each cell of the table. Options for output include printing to the console and to the common markdown formats (markdown, HTML, and LaTeX). With a little 'pixiedust' (and happy thoughts) tables can really fly.


After tidying up your analyses with the broom package, go ahead and grab the pixiedust. Customize your table output and write it to markdown, HTML, LaTeX, or even just the console. pixiedust makes it easy to customize the appearance of your tables in all of these formats by adding any number of "sprinkles", much in the same way you can add layers to a ggplot.

fit <- lm(mpg ~ qsec + factor(am) + wt + factor(gear), data = mtcars)
dust(fit) %>% 
  sprinkle(col = 2:4, round = 3) %>% 
  sprinkle(col = 5, fn = quote(pvalString(value))) %>% 
  sprinkle_colnames(term = "Term", 
                    estimate = "Estimate", 
                     std.error = "SE",
                     statistic = "T-statistic", 
                     p.value = "P-value") %>%
  sprinkle_print_method("console") #> 1   (Intercept)    9.365 8.373       1.118    0.27
#> 2          qsec    1.245 0.383       3.252   0.003
#> 3   factor(am)1    3.151 1.941       1.624    0.12
#> 4            wt   -3.926 0.743      -5.286 < 0.001
#> 5 factor(gear)4   -0.268 1.655      -0.162    0.87
#> 6 factor(gear)5    -0.27 2.063      -0.131     0.9

Tables can be customized by row, column, or even by a single cell by adding sprinkles to the dust object. The table below shows the currently planned and implemented sprinkles. In the "implemented" column, an 'x' indicates a customization that has been implemented, while a blank cell suggests that the customization is planned but has not yet been implemented. In the remaining columns, an 'x' indicates that the sprinkle is already implemented for the output format; an 'o' indicates that implementation is planned but not yet completed; and a blank cell indicates that the sprinkle will not be implemented (usually because the output format doesn't support the option).


To demonstrate, let's look at a simple linear model. We build the model and generate the standard summary.

fit <- lm(mpg ~ qsec + factor(am) + wt + factor(gear), data = mtcars)
#> Call:
#> lm(formula = mpg ~ qsec + factor(am) + wt + factor(gear), data = mtcars)
#> Residuals:
#>     Min      1Q  Median      3Q     Max 
#> -3.5064 -1.5220 -0.7517  1.3841  4.6345 
#> Coefficients:
#>               Estimate Std. Error t value Pr(>|t|)    
#> (Intercept)     9.3650     8.3730   1.118  0.27359    
#> qsec            1.2449     0.3828   3.252  0.00317 ** 
#> factor(am)1     3.1505     1.9405   1.624  0.11654    
#> wt             -3.9263     0.7428  -5.286 1.58e-05 ***
#> factor(gear)4  -0.2682     1.6555  -0.162  0.87257    
#> factor(gear)5  -0.2697     2.0632  -0.131  0.89698    
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> Residual standard error: 2.55 on 26 degrees of freedom
#> Multiple R-squared:  0.8498, Adjusted R-squared:  0.8209 
#> F-statistic: 29.43 on 5 and 26 DF,  p-value: 6.379e-10

While the summary is informative and useful, it is full of "stats-speak" and isn't necessarily in a format that is suitable for publication or submission to a client. The broom package provides the summary in tidy format that, serendipitously, it a lot closer to what we would want for formal reports.

#>            term   estimate std.error  statistic      p.value
#> 1   (Intercept)  9.3650443 8.3730161  1.1184792 2.735903e-01
#> 2          qsec  1.2449212 0.3828479  3.2517387 3.168128e-03
#> 3   factor(am)1  3.1505178 1.9405171  1.6235455 1.165367e-01
#> 4            wt -3.9263022 0.7427562 -5.2861251 1.581735e-05
#> 5 factor(gear)4 -0.2681630 1.6554617 -0.1619868 8.725685e-01
#> 6 factor(gear)5 -0.2697468 2.0631829 -0.1307430 8.969850e-01

It has been observed by some, however, that even this summary isn't quite ready for publication. There are too many decimal places, the p-value employ scientific notation, and column titles like "statistic" don't specify what type of statistic. These kinds of details aren't the purview of broom, however, as broom is focused on tidying the results of a model for further analysis (particularly with respect to comparing slightly varying models).

The pixiedust package diverts from broom's mission here and provides the ability to customize the broom output for presentation. The initial dust object returns a table that is similar to the broom output.

dust(fit) %>%
#>            term   estimate std.error  statistic   p.value
#> 1   (Intercept)  9.3650443 8.3730161  1.1184792 0.2735903
#> 2          qsec  1.2449212 0.3828479  3.2517387 0.0031681
#> 3   factor(am)1  3.1505178 1.9405171  1.6235455 0.1165367
#> 4            wt -3.9263022 0.7427562 -5.2861251  1.58e-05
#> 5 factor(gear)4  -0.268163 1.6554617 -0.1619868 0.8725685
#> 6 factor(gear)5 -0.2697468 2.0631829  -0.130743  0.896985

Where pixiedust shows its strength is the ease of which these tables can be customized. The code below rounds the columns estimate, std.error, and statistic to three decimal places each, and then formats the p.value into a format that happens to be one that I like.

x <- dust(fit) %>% 
  sprinkle(col = 2:4, round = 3) %>% 
  sprinkle(col = 5, fn = quote(pvalString(value))) %>%
#>            term estimate std.error statistic p.value
#> 1   (Intercept)    9.365     8.373     1.118    0.27
#> 2          qsec    1.245     0.383     3.252   0.003
#> 3   factor(am)1    3.151     1.941     1.624    0.12
#> 4            wt   -3.926     0.743    -5.286 < 0.001
#> 5 factor(gear)4   -0.268     1.655    -0.162    0.87
#> 6 factor(gear)5    -0.27     2.063    -0.131     0.9

Now we're almost there! Let's change up the column names, and while we're add it, let's add some "bold" markers to the statistically significant terms in order to make them stand out some (I say "bold" because the console output doesn't show up in bold, but with the markdown tags for bold text. In a rendered table, the text would actually be rendered in bold).

x <- x %>% 
  sprinkle(col = c("estimate", "p.value"), 
           row = c(2, 4), 
           bold = TRUE) %>% 
  sprinkle_colnames(term = "Term", 
                estimate = "Estimate", 
                std.error = "SE",
                statistic = "T-statistic", 
                p.value = "P-value") %>%
#>            Term   Estimate    SE T-statistic     P-value
#> 1   (Intercept)    9.365   8.373       1.118      0.27  
#> 2          qsec  **1.245** 0.383       3.252   **0.003**
#> 3   factor(am)1    3.151   1.941       1.624      0.12  
#> 4            wt **-3.926** 0.743      -5.286 **< 0.001**
#> 5 factor(gear)4   -0.268   1.655      -0.162      0.87  
#> 6 factor(gear)5    -0.27   2.063      -0.131       0.9
VersionRelease DescriptionTarget DateActual Date
0.1.0Console, markdown and HTML output for simple table1 Aug 20153 Aug 2015
0.2.0Multirow table headers; footers; multipage tables20 Aug 201518 Aug 2015
0.3.0Multicolumn and multirow cells in HTML15 Sep 201515 Sept 2015
0.4.0Glance statistics in table footer1 Oct 201525 Sept 2015
Add variable labels and levels to broom output
0.5.0LaTeX output for simple table15 Oct 201515 Oct 2015
Adjustable cell heights and widths in LaTeX tables
Add medley for batch customizations
0.6.0Borders and backgrounds for LaTeX tables1 Dec 20159 Dec 2015
Multicolumn and multirow support for LaTeX tables
Longtable support for LaTeX tables
Rotated text for LaTeX tables
0.7.0bookdown support30 Apr 2016
Auto detect output format (supports knitr/Rmarkdown)
fixed coordinate pairing for sprinkles
Sprinkle recycling
Captions, floating environments, labels
hhline option allows background colors and borders
Methods for grouped and split data frames
1.0.0Release of basic, stable package1 June 2016

bold version numbers indicate a planned release to CRAN.

The markdown output from pixiedust is somewhat limited due to the limitations of Rmarkdown itself. If/when more features become available for Rmarkdown output, I'll be sure to include them. But what can you do if you really want all of the flexibility of the HTML tables but need the MS Word document?

With a little help from the Gmisc package, you can have the best of both worlds. Gmisc isn't available on CRAN yet, but if you're willing to install it from GitHub, you can render a docx file. Install Gmisc with


Then use in your YAML header

output: Gmisc::docx_document

When you knit your document, it knits as an HTML file, but I've had no problems with the rendering when I right-click the file and open with MS Word.

Read more at (but note that this blog post was written about the Grmd package before it was moved into the Gmisc package).


  • Guard against changes to options()$scipen (Issue #62)
  • Remove remaining use of ArgumentCheck and replace with checkmate
  • Fixed rotation in HTML tables
  • Created a new argument for print_dust_html (Issue #57) to give the user control over the amount of white space following HTML tables.
  • The replace sprinkle is now applied during printing. It had been applied in sprinkle, which violated the philosophy of not changing the content of the data frame until the last possible moment.
  • Added some extra unit tests.
  • Fixed the padding specification in HTML tables.
  • the sprinkles bg, border_color and font_color now interpret "transparent" as a valid color. In HTML, it is interpreted as "rgba(255,255,255,0)"; in LaTeX it is interpreted as "".
  • New Sprinkle: sanitize. Defaults to FALSE and replaces automatic sanitization of text in LaTeX output via Hmisc::latexTranslate. This is not backward compatible with 0.7.0, but is consistent with earlier versions of pixiedust. You must opt in to sanitization now.
  • New Sprinkle: sanitize_args. Takes a list of arguments to pass to Hmisc::latexTranslate, allowing sanitization to be extended to character sets defined by the user.
  • Backward compatibility: The way pixiedust deals with colors has changed. If you are using custom defined colors in your LaTeX preamble, these will no longer work. pixiedust will only accept colors names in colors(), or in the rgb, rgba, #RRGGBB, or #RRDDBBAA formats. This only affects LaTeX output, and provides a better interface for ensuring all HTML and LaTeX output are as similar as possible.
  • Added justification for tables. Use the justify argument in dust and the justify sprinkle to move the table to the left, or right side of the page. Defaults to centered.
  • Added auto-detection of the print method. When a document is being knit, the output format is read from knitr::opts_knit$get(""). If this resolves to NULL, the value of getOption("pixiedust_print_method") is used.
  • Added docx as a valid print method, which is synonymous with markdown.
  • labels for HTML and LaTeX tables are automatically generated when label = NULL. First, an attempt is made to generate a label from the chunk label, and if that fails, a label is generated from getOption("pixie_count")
  • Added default horizontal alignments for HTML tables
  • Added default rounding for numerical values. If the user does not give a value, the value of getOption("digits") is used. This effectively prints as many decimal places as would be printed in the console.
  • Sprinkle recycling is added with recycle argument.
  • Fixed coordinate pairs is added with fixed argument.
  • Added recognition of all colors in colors()
  • Converted dust, sprinkle functions, and print to S3 methods. This allows for lists of data frames to be processed as separate tables.
  • Added dust.grouped_df to give the option of ungrouping a grouped_df object, or splitting it.
  • Added the bookdown attribute (and sprinkle) to allow use with the bookdown package.
  • Added labeling.
  • Added caption, hhline, and float as sprinkles.
  • Changed the default colors for bg_pattern to "#FFFFFF#" and "#DDDDDD". The gray in this pattern is a little lighter and should do better when printed in black and white.
  • Implemented a new printing method that makes use of the hhline LaTeX package. This allows borders to be drawn over background colors. In the existing method, the cell borders are hidden by background colors. The hhline method can be used by setting options(pixiedust_latex_hhline = TRUE).
  • Table Captions are now implemented.
  • Added parameter to place LaTeX tables in a float environment. This was necessary to make table captions functional in non-longtable situations.
  • LaTeX output is fully implemented
  • tabrowsep element was removed from the dust object since it apparently isn't a real thing.
  • Implemented rotated text.
  • Pushed version to 0.6.0
  • Finished the borders for LaTeX output. This completes the baseline LaTeX output.
  • Revamped the LateX output again, pretty much started over entirely. But now the only thing missing is cell borders, and my previous work will accommodate those.
  • Added tablewidth, tabcolsep, and tabrowsep elements to the dust object. tablewidth allows the user to define cell width in terms of a percentage of the total expected table width. Not really recommended, but at least preserves some continuity between HTML and LaTeX output.
  • tabcolsep and tabrowsep control the distance between columns and rows in tables, but this feature isn't yet implemented.
  • Documentation is lacking on tablewidth, tabcolsep, and tabrowsep
  • Added the font_family sprinkle for HTML output
  • Due to a great deal of difficulty getting the last couple of features to play nicely, I decided to take a different approach to the LaTeX output. Most features are available, but I have yet to include column widths, column heights, or multirow output.
  • An option is added to the print method that turns off the knitr::asis_output return. The motivation behind this was to be able to use the HTML code in shiny applications.
  • Longtable support is added
  • Documentation on cell borders is up to date
  • Cell borders. Documentation still needs review.
  • pixiedust no longer uses the + operator.
    Please use %>% instead.
  • Complete support for HTML tables is available.
  • Limited support for LaTeX tables is available.
  • New vignette: Advanced Magic.
  • Added the replace sprinkle to replace values in table columns, rows, or cells.
  • Added the longtable sprinkle: allows tables to be printed in multiple sections.
  • Added the na_string sprinkle.
  • Added support for multirow headers and footers.
  • Added support for multicell output using the merge sprinkle.
  • Added an option glance_foot, which places model summary statistics in the foot of a table.
  • Added options for including variables labels and more detailed descriptions of factors and levels.
  • Introduces "medleys", functions that can apply multiple sprinkles to a dust object in a single line.
  • Adds method
  • The majority of LaTeX sprinkles are available, with the exception of borders, longtable, merging cells, and rotated text.
  • Added basic medleys
  • Adds method. Closes Issue #33
  • Started LaTeX Output
  • Fixed a bug described in Issue #26
  • Changes to Advance Magic vignette use a linear model and glance statistics for examples.
  • Glance footer is implemented. Vignettes need to be updated
  • Variable labels and levels are implemented (well ahead of schedule!). Vignettes need to be updated
  • Multi-cell output for HTML is fully supported.
  • Data frame row names may be captured in the output with dust argument keep_rownames
  • A new sprinkle is added. na_string defaults to "", and controls how NA is printed in tables.
  • Multi-cell output is functional for HTML, Markdown, and Console output
  • A poor example is added to the advancedMagic vignette, but a better example is really needed.
  • Finished the Advanced Magic vignette, which serves as the tests for advanced output since I haven't bothered to code a way to check the results directly.
  • Configure the repository for coveralls.
  • Adds covr and Hmisc to Suggests:
  • Removed 'longtable' option from print.dust and made it a sprinkle. This allows it to be used without having to explicitly call print.
  • Implemented longtable capacity. Users may now break tables into multiple divisions of either a default size (25 rows for console, markdown, or HTML) or a user-specified number of rows.
  • Began an "advanced magic" vignette to demonstrate the capabilities of longtable and eventually multicolumn and multirow support. Similar vignettes will be needed for console, markdown, and html output, though not all of them will need to be bundled with the package.
  • Added the roundSafe helper function to allow rounding to succeed while skipping true character values.
  • Added the longtable option to print.dust. Not yet active, but lays the groundwork for multipage tables.
  • Added multirow headers and footers (but not interfoot)
  • Added the redust function for adding and/or switching table components. For example, adding a multirow header, or a foot.
  • Added the replace sprinkle to replace values in table columns, rows, or cells. This closes Issue #12
  • Optimizations related to removing ifelse calls.
  • Initial values for table attributes are now stored as "" instead of NA. This increases the object size, but cuts down on the processing time.
  • Removed object element from the dust object. In Issue #13, matthieugomez pointed out that very large models could create storage space problems. There's no sense in keeping an extra copy of the model object.
  • Removed the +.dust method and rewrote the sprinkles as pipable functions. This resolves Issue #8
  • Added the necessary fields to DESCRIPTION to get the vignettes to build.
  • CRAN checks are passed. Prepared for release.
  • Finished tests
  • Finished vignettes
  • Finished HTML rendering
  • Adds pixiedust vignette
  • Removes old vignettes
  • Replace nearly all dust bunny functions with sprinkle
  • Replace dust_print_method with sprinkle_print_method
  • Replace dust_colnames with sprinkle_colnames
  • It occurred to me as I studied the code base that instead of rows and cols in the ... argument of the dust bunnies, it made more sense to add the dust bunnies in ... with formal arguments for row and col. I also came up with the idea of naming the package pixiedust and sprinkling the dust around. It sounded like fun so let's hope CRAN lets me get away with it.
  • All functionality has been rewritten to support the pixiedust paradigm, but new tests and vignettes need to be written to confirm that it all works.
  • R CMD check has NOT been run.
  • Adds dust_rotate_text
  • Adds dust_cell_valign
  • Adds dust_border_collapse
  • Adds dust_table_border
  • Adds dust_cell_border
  • Adds dust_cell_padding
  • Improved the Dustbunnies vignette to use a color coded table indicating which dust bunnies are planned, available, and functional for different printing methods.
  • Dropped leading zeroes from the version number.
  • Adds dust_font_color, dust_font_size
  • Adds dust_cell_height, dust_cell_width
  • Adds halign and valign attributes to dust$obj. valign is not yet implemented.
  • Adds dust_cell_halign
  • Adds dust_head_halign
  • Adds dustbunnies vignette
  • Removed the col_names attribute of the dust object and replaced it with the head object. The head object is a data frame holding the attributes of the table header.
  • Renamed the obj attributes of the dust object to body.
  • Adds a lot of tests
  • Adds dust_cell_bg and dust_bg_pattern
  • 'col_namesattribute is now named. The names are the original column names from thebroom` output.
  • Adds dust_fn
  • Adds dust_bold
  • Adds dust_italic
  • Adds dust_print_format
  • Imports knitr
  • Imports lazyWeave::pvalString
  • Adds dust and print.dust.
  • Only the method for printing to the console is available.
  • +.dust added
  • dust_colnames added

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.


0.8.1 by Benjamin Nutter, 3 months ago

Report a bug at

Browse source code at

Authors: Benjamin Nutter [aut, cre], David Kretch [ctb]

Documentation:   PDF Manual  

MIT + file LICENSE license

Imports broom, checkmate, dplyr, Hmisc, htmltools, knitr, magrittr, scales, stringr, tidyr

Suggests rmarkdown, testthat

Imported by HydeNet, pointblank, tadaatoolbox.

See at CRAN