Advanced Magic with pixiedust
Author: Benjamin Nutter
Date: 2023-10-09

# Advanced Magic with `pixiedust`

#### Benjamin Nutter

#### 2023-10-09

In addition to the basic cell-specific customizations covered in the “pixiedust” vignette (`vignette("pixiedust")`), `pixiedust` also supports some more advanced features for displaying tabular output. Specifically, you can add multi-row headers and footers; display your tables in multiple divisions; and create cells that span multiple columns and/or rows.

The presentation of this vignette will be a hybrid of tutorial and testing environment. Due to the way that `pixiedust` generates output, it cannot be directly evaluated for accuracy (this may change some day, but not right now) and so the best way to see if it is doing what is expected is to generate the output. The primary tutorial aspect of this vignette will be covered in the HTML portions, with the Markdown and Console output being provided mostly to verify that the output is as expected.

For parts of this vignette, we will work with the `mtcars` data frame. But first we make some additions to the data. For simplicity, we will only use the first ten rows of the data frame. Additionally, we will add labels to the variables using the `set_label` function from the `labelVector` package.

    library(dplyr)

    ##
    ## Attaching package: 'dplyr'

    ## The following objects are masked from 'package:stats':
    ##
    ##     filter, lag

    ## The following objects are masked from 'package:base':
    ##
    ##     intersect, setdiff, setequal, union

    library(pixiedust)

    mtcars2 <- mtcars[1:10, ]
    mtcars2 <-
      labelVector::set_label(
        mtcars2,
        mpg = "Gas Mileage",
        cyl = "Cylinders",
        disp = "Displacement",
        hp = "Horse Power",
        drat = "Rear Axle Ratio",
        wt = "Weight",
        qsec = "1/4 mile time",
        vs = "V/S",
        am = "Transmission",
        gear = "Forward Gears",
        carb = "Carburetors")

In other portions of the vignette, we will use a linear model based on the full `mtcars` data set. We will assign the same variable labels shown above. We will also create a couple of factor variables to show how factors can be displayed.

# 1 HTML Output

## 1.1 Multirow Headers and Footers

To illustrate the multirow headers and footers, we will generate a header that has both the column name and the label. The footer will summarise the values in each column by mean and standard deviation.

    custom_head <- rbind(names(mtcars2),
                         labelVector::get_label(mtcars2,
                                                names(mtcars2))) %>%
      as.data.frame(stringsAsFactors = FALSE)

    custom_foot <- rbind(vapply(mtcars2, mean, numeric(1)),
                         vapply(mtcars2, sd, numeric(1))) %>%
      as.data.frame(stringsAsFactors = FALSE)

Now we need only create a `dust` object and add our custom header and footer. To replace components of the `dust` object, we “`redust`” the component. We’ll also shade the head and foot in different shades of gray to make them stand out.

    dust(mtcars2) %>%
      redust(custom_head, part = "head") %>%
      redust(custom_foot, part = "foot") %>%
      sprinkle_table(round = 2) %>%
      sprinkle(bg = "gray", part = "head") %>%
      sprinkle(bg = "lightgray", part = "foot") %>%
      sprinkle_print_method("html")

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
21 | 6 | 160 | 110 | 3.9 | 2.62 | 16.46 | 0 | 1 | 4 | 4
21 | 6 | 160 | 110 | 3.9 | 2.88 | 17.02 | 0 | 1 | 4 | 4
22.8 | 4 | 108 | 93 | 3.85 | 2.32 | 18.61 | 1 | 1 | 4 | 1
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.44 | 1 | 0 | 3 | 1
18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17.02 | 0 | 0 | 3 | 2
18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.22 | 1 | 0 | 3 | 1
14.3 | 8 | 360 | 245 | 3.21 | 3.57 | 15.84 | 0 | 0 | 3 | 4
24.4 | 4 | 146.7 | 62 | 3.69 | 3.19 | 20 | 1 | 0 | 4 | 2
22.8 | 4 | 140.8 | 95 | 3.92 | 3.15 | 22.9 | 1 | 0 | 4 | 2
19.2 | 6 | 167.6 | 123 | 3.92 | 3.44 | 18.3 | 1 | 0 | 4 | 4
20.37 | 5.8 | 208.61 | 122.8 | 3.54 | 3.13 | 18.58 | 0.6 | 0.3 | 3.6 | 2.5
2.91 | 1.48 | 90.37 | 51.45 | 0.44 | 0.41 | 2.14 | 0.52 | 0.48 | 0.52 | 1.35

## 1.2 Longtable Feature

The longtable feature is named for the LaTeX package `longtable`, which will automatically break a table into multiple divisions, each of which is displayed on a separate page. We can use the long table sprinkle to break a table into divisions of any size we like. In this example, we’ll use divisions of four rows each. We will use the same header and footer as the previous example, and we’ll also make use of the interfoot, which is the footer placed at the bottom of each intermediate table, while the footer is placed only at the bottom of the last table. We’ll make use of the multi-cell feature for the interfoot here, although we won’t really discuss it until the next section.

The code for this table is nearly identical to the previous example. We just add a `redust` call for the interfoot and add a `longtable` argument to `sprinkle_table`.

    custom_interfoot <- data.frame("To Be Continued",
                                   "", "", "", "", "", "",
                                   "", "", "", "")

    (x <- dust(mtcars2) %>%
      redust(custom_head, part = "head") %>%
      redust(custom_foot, part = "foot") %>%
      redust(custom_interfoot, part = "interfoot") %>%
      sprinkle_table(round = 2, longtable = 4) %>%
      sprinkle(bg = "gray", part = "head") %>%
      sprinkle(bg = "lightgray", part = "foot") %>%
      sprinkle(bg = "lightgray", part = "interfoot") %>%
      sprinkle_print_method("html"))

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
21 | 6 | 160 | 110 | 3.9 | 2.62 | 16.46 | 0 | 1 | 4 | 4
21 | 6 | 160 | 110 | 3.9 | 2.88 | 17.02 | 0 | 1 | 4 | 4
22.8 | 4 | 108 | 93 | 3.85 | 2.32 | 18.61 | 1 | 1 | 4 | 1
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.44 | 1 | 0 | 3 | 1
To Be Continued |  |  |  |  |  |  |  |  |  |

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17.02 | 0 | 0 | 3 | 2
18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.22 | 1 | 0 | 3 | 1
14.3 | 8 | 360 | 245 | 3.21 | 3.57 | 15.84 | 0 | 0 | 3 | 4
24.4 | 4 | 146.7 | 62 | 3.69 | 3.19 | 20 | 1 | 0 | 4 | 2
To Be Continued |  |  |  |  |  |  |  |  |  |

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
22.8 | 4 | 140.8 | 95 | 3.92 | 3.15 | 22.9 | 1 | 0 | 4 | 2
19.2 | 6 | 167.6 | 123 | 3.92 | 3.44 | 18.3 | 1 | 0 | 4 | 4
20.37 | 5.8 | 208.61 | 122.8 | 3.54 | 3.13 | 18.58 | 0.6 | 0.3 | 3.6 | 2.5
2.91 | 1.48 | 90.37 | 51.45 | 0.44 | 0.41 | 2.14 | 0.52 | 0.48 | 0.52 | 1.35

## 1.3 Multi-cell Representations

The table above doesn’t look quite right, however, because the “To Be Continued” appears in one cell when it might look better spread out on a single line. We can use the `merge` sprinkle to merge all of the cells in the `interfoot` in order to make it appear more fluid.

    x %>%
      sprinkle(merge = TRUE, halign = "center", part = "interfoot")

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
21 | 6 | 160 | 110 | 3.9 | 2.62 | 16.46 | 0 | 1 | 4 | 4
21 | 6 | 160 | 110 | 3.9 | 2.88 | 17.02 | 0 | 1 | 4 | 4
22.8 | 4 | 108 | 93 | 3.85 | 2.32 | 18.61 | 1 | 1 | 4 | 1
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.44 | 1 | 0 | 3 | 1
To Be Continued

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17.02 | 0 | 0 | 3 | 2
18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.22 | 1 | 0 | 3 | 1
14.3 | 8 | 360 | 245 | 3.21 | 3.57 | 15.84 | 0 | 0 | 3 | 4
24.4 | 4 | 146.7 | 62 | 3.69 | 3.19 | 20 | 1 | 0 | 4 | 2
To Be Continued

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
22.8 | 4 | 140.8 | 95 | 3.92 | 3.15 | 22.9 | 1 | 0 | 4 | 2
19.2 | 6 | 167.6 | 123 | 3.92 | 3.44 | 18.3 | 1 | 0 | 4 | 4
20.37 | 5.8 | 208.61 | 122.8 | 3.54 | 3.13 | 18.58 | 0.6 | 0.3 | 3.6 | 2.5
2.91 | 1.48 | 90.37 | 51.45 | 0.44 | 0.41 | 2.14 | 0.52 | 0.48 | 0.52 | 1.35

The `merge` sprinkle may be used to join any number of conjoined cells. The following example is for illustration only, and probably wouldn’t be put to use in any meaningful application. What we will do is merge nine cells and display the value of the center cell. Take notice of where the value `160` appears in the table below compared to the table above.

    x %>%
      sprinkle(merge = TRUE, halign = "center", part = "interfoot") %>%
      sprinkle(rows = 1:3, cols = 2:4,
               merge = TRUE, merge_rowval = 2, merge_colval = 3,
               halign = "center")

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
21 | 160 | 3.9 | 2.62 | 16.46 | 0 | 1 | 4 | 4
21 | 3.9 | 2.88 | 17.02 | 0 | 1 | 4 | 4
22.8 | 3.85 | 2.32 | 18.61 | 1 | 1 | 4 | 1
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.44 | 1 | 0 | 3 | 1
To Be Continued

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17.02 | 0 | 0 | 3 | 2
18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.22 | 1 | 0 | 3 | 1
14.3 | 8 | 360 | 245 | 3.21 | 3.57 | 15.84 | 0 | 0 | 3 | 4
24.4 | 4 | 146.7 | 62 | 3.69 | 3.19 | 20 | 1 | 0 | 4 | 2
To Be Continued

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
22.8 | 4 | 140.8 | 95 | 3.92 | 3.15 | 22.9 | 1 | 0 | 4 | 2
19.2 | 6 | 167.6 | 123 | 3.92 | 3.44 | 18.3 | 1 | 0 | 4 | 4
20.37 | 5.8 | 208.61 | 122.8 | 3.54 | 3.13 | 18.58 | 0.6 | 0.3 | 3.6 | 2.5
2.91 | 1.48 | 90.37 | 51.45 | 0.44 | 0.41 | 2.14 | 0.52 | 0.48 | 0.52 | 1.35

## 1.4 Model Summaries with Fit Statistics

`pixiedust` offers a few options to help simplify the preparation of model output for tabular display. If you choose to use the `label` functions from the `labelVector` package, these labels can be accessed for the table. Additionally, the levels of factor variables may be printed in a more human-readable format. (note that the `label` functions from the `Hmisc` package may also be used)

    fit <- lm(mpg ~ qsec + factor(am) + wt + factor(gear),
              data = mtcars)

    dust(fit, descriptors = c("label", "level")) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle_print_method("html")

label | level | estimate | std.error | statistic | p.value
--- | --- | --- | --- | --- | ---
(Intercept) | NA | 9.37 | 8.37 | 1.12 | 0.27
NA | Manual | 3.15 | 1.94 | 1.62 | 0.12
NA | 4 | -0.27 | 1.66 | -0.16 | 0.87
NA | 5 | -0.27 | 2.06 | -0.13 | 0.9
NA |  | 1.24 | 0.38 | 3.25 | 0.003
NA |  | -3.93 | 0.74 | -5.29 | < 0.001

Or, if we wish to see the reference value of the factors, we can request the `"level_detail"` descriptor.

    dust(fit, descriptors = c("label", "level_detail")) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle_print_method("html")

label | level_detail | estimate | std.error | statistic | p.value
--- | --- | --- | --- | --- | ---
(Intercept) | NA | 9.37 | 8.37 | 1.12 | 0.27
NA | Manual vs. Automatic | 3.15 | 1.94 | 1.62 | 0.12
NA | 4 vs. 3 | -0.27 | 1.66 | -0.16 | 0.87
NA | 5 vs. 3 | -0.27 | 2.06 | -0.13 | 0.9
NA |  | 1.24 | 0.38 | 3.25 | 0.003
NA |  | -3.93 | 0.74 | -5.29 | < 0.001

One word of caution: The labels are pulled from the data obtained by `model.frame`, and if you apply a function to a term in your formula, you might lose the label. Consider the example below, where we include the `vs` variable, but convert it from a numeric to a factor. If retaining the label is important to you, making your conversions prior to assigning the labels will be a good habit. Don’t fret too much, however, as you can always replace a cell’s content with the `replace` sprinkle.

    fit <- lm(mpg ~ qsec + am + wt + gear + factor(vs),
              data = mtcars)

    dust(fit, descriptors = c("label", "level_detail")) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle_print_method("html")

label | level_detail | estimate | std.error | statistic | p.value
--- | --- | --- | --- | --- | ---
(Intercept) | NA | 9.55 | 9.45 | 1.01 | 0.32
NA | Manual vs. Automatic | 3.17 | 2.01 | 1.58 | 0.13
NA | 1 vs. 0 | 0.09 | 1.92 | 0.05 | 0.96
NA | 4 vs. 3 | -0.29 | 1.77 | -0.17 | 0.87
NA | 5 vs. 3 | -0.29 | 2.17 | -0.14 | 0.89
NA |  | 1.23 | 0.51 | 2.39 | 0.025
NA |  | -3.91 | 0.85 | -4.62 | < 0.001

In addition to providing better labeling of terms and factor levels, `pixiedust` allows you to add model fit statistics in a similar manner that the `stargazer` package does. Under the default settings, we can build these statistics in the following manner:

    fit <- lm(mpg ~ qsec + am + wt + gear,
              data = mtcars)

    dust(fit, descriptors = c("label", "level_detail"),
         glance_foot = TRUE) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle(rows = 1, border = "top") %>%
      sprinkle(cols = c(2, 6), round = 2, na_string = "",
               part = "foot") %>%
      sprinkle(rows = 1, border = "top", part = "foot") %>%
      sprinkle_print_method("html")

label | level_detail | estimate | std.error | statistic | p.value
--- | --- | --- | --- | --- | ---
(Intercept) | NA | 9.37 | 8.37 | 1.12 | 0.27
NA | Manual vs. Automatic | 3.15 | 1.94 | 1.62 | 0.12
NA | 4 vs. 3 | -0.27 | 1.66 | -0.16 | 0.87
NA | 5 vs. 3 | -0.27 | 2.06 | -0.13 | 0.9
NA |  | 1.24 | 0.38 | 3.25 | 0.003
NA |  | -3.93 | 0.74 | -5.29 | < 0.001
r.squared | 0.85 |  |  | logLik | -72.04
adj.r.squared | 0.82 |  |  | AIC | 158.08
sigma | 2.55 |  |  | BIC | 168.34
statistic | 29.43 |  |  | deviance | 169.1
p.value | 0 |  |  | df.residual | 26
df | 5 |  |  | nobs | 32

At times, we may find the volume of these fit statistics overwhelming and may want to display only a subset of them. This can be done with the use of the `glance_stats` argument in `dust`. In addition to selecting the statistics to display, the order in which they are displayed may also be controlled.

    fit <- lm(mpg ~ qsec + am + wt + gear,
              data = mtcars)

    dust(fit, descriptors = c("label", "level_detail"),
         glance_foot = TRUE,
         glance_stats = c("AIC", "adj.r.squared", "BIC", "df"),
         byrow = TRUE) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle(rows = 1, border = "top") %>%
      sprinkle(cols = c(2, 6), round = 2, na_string = "",
               part = "foot") %>%
      sprinkle(rows = 1, border = "top", part = "foot") %>%
      sprinkle_print_method("html")

label | level_detail | estimate | std.error | statistic | p.value
--- | --- | --- | --- | --- | ---
(Intercept) | NA | 9.37 | 8.37 | 1.12 | 0.27
NA | Manual vs. Automatic | 3.15 | 1.94 | 1.62 | 0.12
NA | 4 vs. 3 | -0.27 | 1.66 | -0.16 | 0.87
NA | 5 vs. 3 | -0.27 | 2.06 | -0.13 | 0.9
NA |  | 1.24 | 0.38 | 3.25 | 0.003
NA |  | -3.93 | 0.74 | -5.29 | < 0.001
AIC | 158.08 |  |  | adj.r.squared | 0.82
BIC | 168.34 |  |  | df | 5

# 2 Console Output

The console output isn’t as sophisticated as the HTML output, and so not all of the sprinkles applied to the HTML table will show up in the console. Background shading in particular doesn’t appear in the console. Multirow headers and footers still work, however.

## 2.1 Multirow Headers and Footers

To illustrate the multirow headers and footers, we will generate a header that has both the column name and the label. The footer will summarise the values in each column by mean and standard deviation.

    custom_head <- rbind(names(mtcars2),
                         labelVector::get_label(mtcars2,
                                                names(mtcars2))) %>%
      as.data.frame(stringsAsFactors = FALSE)

    custom_foot <- rbind(vapply(mtcars2, mean, numeric(1)),
                         vapply(mtcars2, sd, numeric(1))) %>%
      as.data.frame(stringsAsFactors = FALSE)

Now we need only create a `dust` object and add our custom header and footer. To replace components of the `dust` object, we “`redust`” the component. We’ll also shade the head and foot in different shades of gray to make them stand out.

    dust(mtcars2) %>%
      redust(custom_head, part = "head") %>%
      redust(custom_foot, part = "foot") %>%
      sprinkle_table(round = 2) %>%
      sprinkle(bg = "gray", part = "head") %>%
      sprinkle(bg = "lightgray", part = "foot") %>%
      sprinkle_print_method("console")

    ##            mpg       cyl         disp          hp            drat     wt
    ## 2  Gas Mileage Cylinders Displacement Horse Power Rear Axle Ratio Weight
    ## 1           21         6          160         110             3.9   2.62
    ## 21          21         6          160         110             3.9   2.88
    ## 3         22.8         4          108          93            3.85   2.32
    ## 4         21.4         6          258         110            3.08   3.21
    ## 5         18.7         8          360         175            3.15   3.44
    ## 6         18.1         6          225         105            2.76   3.46
    ## 7         14.3         8          360         245            3.21   3.57
    ## 8         24.4         4        146.7          62            3.69   3.19
    ## 9         22.8         4        140.8          95            3.92   3.15
    ## 10        19.2         6        167.6         123            3.92   3.44
    ## 11       20.37       5.8       208.61       122.8            3.54   3.13
    ## 22        2.91      1.48        90.37       51.45            0.44   0.41
    ##             qsec   vs           am          gear        carb
    ## 2  1/4 mile time  V/S Transmission Forward Gears Carburetors
    ## 1          16.46    0            1             4           4
    ## 21         17.02    0            1             4           4
    ## 3          18.61    1            1             4           1
    ## 4          19.44    1            0             3           1
    ## 5          17.02    0            0             3           2
    ## 6          20.22    1            0             3           1
    ## 7          15.84    0            0             3           4
    ## 8             20    1            0             4           2
    ## 9           22.9    1            0             4           2
    ## 10          18.3    1            0             4           4
    ## 11         18.58  0.6          0.3           3.6         2.5
    ## 22          2.14 0.52         0.48          0.52        1.35

## 2.2 Longtable Feature

The longtable feature is named for the LaTeX package `longtable`, which will automatically break a table into multiple divisions, each of which is displayed on a separate page. We can use the long table sprinkle to break a table into divisions of any size we like. In this example, we’ll use divisions of four rows each. We will use the same header and footer as the previous example, and we’ll also make use of the interfoot, which is the footer placed at the bottom of each intermediate table, while the footer is placed only at the bottom of the last table. We’ll make use of the multi-cell feature for the interfoot here, although we won’t really discuss it until the next section.

The code for this table is nearly identical to the previous example. We just add a `redust` call for the interfoot and add a `longtable` argument to `sprinkle_table`.

    custom_interfoot <- data.frame("To Be Continued",
                                   "", "", "", "", "", "",
                                   "", "", "", "")

    (x <- dust(mtcars2) %>%
      redust(custom_head, part = "head") %>%
      redust(custom_foot, part = "foot") %>%
      redust(custom_interfoot, part = "interfoot") %>%
      sprinkle_table(round = 2, longtable = 4) %>%
      sprinkle(bg = "gray", part = "head") %>%
      sprinkle(bg = "lightgray", part = "foot") %>%
      sprinkle(bg = "lightgray", part = "interfoot") %>%
      sprinkle_print_method("console"))

    ##                mpg       cyl         disp          hp            drat     wt
    ## 2      Gas Mileage Cylinders Displacement Horse Power Rear Axle Ratio Weight
    ## 1               21         6          160         110             3.9   2.62
    ## 21              21         6          160         110             3.9   2.88
    ## 3             22.8         4          108          93            3.85   2.32
    ## 4             21.4         6          258         110            3.08   3.21
    ## 11 To Be Continued
    ##             qsec  vs           am          gear        carb
    ## 2  1/4 mile time V/S Transmission Forward Gears Carburetors
    ## 1          16.46   0            1             4           4
    ## 21         17.02   0            1             4           4
    ## 3          18.61   1            1             4           1
    ## 4          19.44   1            0             3           1
    ## 11
    ##
    ##
    ##               mpg       cyl         disp          hp            drat     wt
    ## 2     Gas Mileage Cylinders Displacement Horse Power Rear Axle Ratio Weight
    ## 5            18.7         8          360         175            3.15   3.44
    ## 6            18.1         6          225         105            2.76   3.46
    ## 7            14.3         8          360         245            3.21   3.57
    ## 8            24.4         4        146.7          62            3.69   3.19
    ## 1 To Be Continued
    ##            qsec  vs           am          gear        carb
    ## 2 1/4 mile time V/S Transmission Forward Gears Carburetors
    ## 5         17.02   0            0             3           2
    ## 6         20.22   1            0             3           1
    ## 7         15.84   0            0             3           4
    ## 8            20   1            0             4           2
    ## 1
    ##
    ##
    ##            mpg       cyl         disp          hp            drat     wt
    ## 2  Gas Mileage Cylinders Displacement Horse Power Rear Axle Ratio Weight
    ## 9         22.8         4        140.8          95            3.92   3.15
    ## 10        19.2         6        167.6         123            3.92   3.44
    ## 1        20.37       5.8       208.61       122.8            3.54   3.13
    ## 21        2.91      1.48        90.37       51.45            0.44   0.41
    ##             qsec   vs           am          gear        carb
    ## 2  1/4 mile time  V/S Transmission Forward Gears Carburetors
    ## 9           22.9    1            0             4           2
    ## 10          18.3    1            0             4           4
    ## 1          18.58  0.6          0.3           3.6         2.5
    ## 21          2.14 0.52         0.48          0.52        1.35

## 2.3 Multi-cell Representations

The table above doesn’t look quite right, however, because the “To Be Continued” appears in one cell when it might look better spread out on a single line. With the HTML output, we could use the `merge` sprinkle to merge all of the cells in the `interfoot` in order to make it appear more fluid. However, this feature isn’t supported by the console, so the best we can get is the text in one cell.

    x %>%
      sprinkle(merge = TRUE, halign = "center", part = "interfoot")

    ##                mpg       cyl         disp          hp            drat     wt
    ## 2      Gas Mileage Cylinders Displacement Horse Power Rear Axle Ratio Weight
    ## 1               21         6          160         110             3.9   2.62
    ## 21              21         6          160         110             3.9   2.88
    ## 3             22.8         4          108          93            3.85   2.32
    ## 4             21.4         6          258         110            3.08   3.21
    ## 11 To Be Continued
    ##             qsec  vs           am          gear        carb
    ## 2  1/4 mile time V/S Transmission Forward Gears Carburetors
    ## 1          16.46   0            1             4           4
    ## 21         17.02   0            1             4           4
    ## 3          18.61   1            1             4           1
    ## 4          19.44   1            0             3           1
    ## 11
    ##
    ##
    ##               mpg       cyl         disp          hp            drat     wt
    ## 2     Gas Mileage Cylinders Displacement Horse Power Rear Axle Ratio Weight
    ## 5            18.7         8          360         175            3.15   3.44
    ## 6            18.1         6          225         105            2.76   3.46
    ## 7            14.3         8          360         245            3.21   3.57
    ## 8            24.4         4        146.7          62            3.69   3.19
    ## 1 To Be Continued
    ##            qsec  vs           am          gear        carb
    ## 2 1/4 mile time V/S Transmission Forward Gears Carburetors
    ## 5         17.02   0            0             3           2
    ## 6         20.22   1            0             3           1
    ## 7         15.84   0            0             3           4
    ## 8            20   1            0             4           2
    ## 1
    ##
    ##
    ##            mpg       cyl         disp          hp            drat     wt
    ## 2  Gas Mileage Cylinders Displacement Horse Power Rear Axle Ratio Weight
    ## 9         22.8         4        140.8          95            3.92   3.15
    ## 10        19.2         6        167.6         123            3.92   3.44
    ## 1        20.37       5.8       208.61       122.8            3.54   3.13
    ## 21        2.91      1.48        90.37       51.45            0.44   0.41
    ##             qsec   vs           am          gear        carb
    ## 2  1/4 mile time  V/S Transmission Forward Gears Carburetors
    ## 9           22.9    1            0             4           2
    ## 10          18.3    1            0             4           4
    ## 1          18.58  0.6          0.3           3.6         2.5
    ## 21          2.14 0.52         0.48          0.52        1.35

The `merge` sprinkle may be used to join any number of conjoined cells. The following example is for illustration only, and probably wouldn’t be put to use in any meaningful application. What we will do is merge nine cells and display the value of the center cell. Take notice of where the value `160` appears in the table below compared to the table above. In the case of markdown output, the cells aren’t actually merged, but the values of the non-displayed cells are set to `""`.

    x %>%
      sprinkle(merge = TRUE, halign = "center", part = "interfoot") %>%
      sprinkle(rows = 1:3, cols = 2:4,
               merge = TRUE, merge_rowval = 2, merge_colval = 3,
               halign = "center")

    ##                mpg       cyl         disp          hp            drat     wt
    ## 2      Gas Mileage Cylinders Displacement Horse Power Rear Axle Ratio Weight
    ## 1               21                                                3.9   2.62
    ## 21              21                    160                         3.9   2.88
    ## 3             22.8                                               3.85   2.32
    ## 4             21.4         6          258         110            3.08   3.21
    ## 11 To Be Continued
    ##             qsec  vs           am          gear        carb
    ## 2  1/4 mile time V/S Transmission Forward Gears Carburetors
    ## 1          16.46   0            1             4           4
    ## 21         17.02   0            1             4           4
    ## 3          18.61   1            1             4           1
    ## 4          19.44   1            0             3           1
    ## 11
    ##
    ##
    ##               mpg       cyl         disp          hp            drat     wt
    ## 2     Gas Mileage Cylinders Displacement Horse Power Rear Axle Ratio Weight
    ## 5            18.7         8          360         175            3.15   3.44
    ## 6            18.1         6          225         105            2.76   3.46
    ## 7            14.3         8          360         245            3.21   3.57
    ## 8            24.4         4        146.7          62            3.69   3.19
    ## 1 To Be Continued
    ##            qsec  vs           am          gear        carb
    ## 2 1/4 mile time V/S Transmission Forward Gears Carburetors
    ## 5         17.02   0            0             3           2
    ## 6         20.22   1            0             3           1
    ## 7         15.84   0            0             3           4
    ## 8            20   1            0             4           2
    ## 1
    ##
    ##
    ##            mpg       cyl         disp          hp            drat     wt
    ## 2  Gas Mileage Cylinders Displacement Horse Power Rear Axle Ratio Weight
    ## 9         22.8         4        140.8          95            3.92   3.15
    ## 10        19.2         6        167.6         123            3.92   3.44
    ## 1        20.37       5.8       208.61       122.8            3.54   3.13
    ## 21        2.91      1.48        90.37       51.45            0.44   0.41
    ##             qsec   vs           am          gear        carb
    ## 2  1/4 mile time  V/S Transmission Forward Gears Carburetors
    ## 9           22.9    1            0             4           2
    ## 10          18.3    1            0             4           4
    ## 1          18.58  0.6          0.3           3.6         2.5
    ## 21          2.14 0.52         0.48          0.52        1.35

## 2.4 Model Summaries with Fit Statistics

`pixiedust` offers a few options to help simplify the preparation of model output for tabular display. If you choose to use the `label` functions from the `labelVector` package, these labels can be accessed for the table. Additionally, the levels of factor variables may be printed in a more human-readable format. (note that the `label` functions from the `Hmisc` package may also be used)

    fit <- lm(mpg ~ qsec + factor(am) + wt + factor(gear),
              data = mtcars)

    dust(fit, descriptors = c("label", "level")) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle_print_method("console")

    ##         label  level estimate std.error statistic p.value
    ## 1 (Intercept)   <NA>     9.37      8.37      1.12    0.27
    ## 2        <NA> Manual     3.15      1.94      1.62    0.12
    ## 3        <NA>      4    -0.27      1.66     -0.16    0.87
    ## 4        <NA>      5    -0.27      2.06     -0.13     0.9
    ## 5        <NA>            1.24      0.38      3.25   0.003
    ## 6        <NA>           -3.93      0.74     -5.29 < 0.001

Or, if we wish to see the reference value of the factors, we can request the `"level_detail"` descriptor.

    dust(fit, descriptors = c("label", "level_detail")) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle_print_method("console")

    ##         label         level_detail estimate std.error statistic p.value
    ## 1 (Intercept)                 <NA>     9.37      8.37      1.12    0.27
    ## 2        <NA> Manual vs. Automatic     3.15      1.94      1.62    0.12
    ## 3        <NA>              4 vs. 3    -0.27      1.66     -0.16    0.87
    ## 4        <NA>              5 vs. 3    -0.27      2.06     -0.13     0.9
    ## 5        <NA>                          1.24      0.38      3.25   0.003
    ## 6        <NA>                         -3.93      0.74     -5.29 < 0.001

One word of caution: The labels are pulled from the data obtained by `model.frame`, and if you apply a function to a term in your formula, you might lose the label. Consider the example below, where we include the `vs` variable, but convert it from a numeric to a factor. If retaining the label is important to you, making your conversions prior to assigning the labels will be a good habit. Don’t fret too much, however, as you can always replace a cell’s content with the `replace` sprinkle.

    fit <- lm(mpg ~ qsec + am + wt + gear + factor(vs),
              data = mtcars)

    dust(fit, descriptors = c("label", "level_detail")) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle_print_method("console")

    ##         label         level_detail estimate std.error statistic p.value
    ## 1 (Intercept)                 <NA>     9.55      9.45      1.01    0.32
    ## 2        <NA> Manual vs. Automatic     3.17      2.01      1.58    0.13
    ## 3        <NA>              1 vs. 0     0.09      1.92      0.05    0.96
    ## 4        <NA>              4 vs. 3    -0.29      1.77     -0.17    0.87
    ## 5        <NA>              5 vs. 3    -0.29      2.17     -0.14    0.89
    ## 6        <NA>                          1.23      0.51      2.39   0.025
    ## 7        <NA>                         -3.91      0.85     -4.62 < 0.001

In addition to providing better labeling of terms and factor levels, `pixiedust` allows you to add model fit statistics in a similar manner that the `stargazer` package does. Under the default settings, we can build these statistics in the following manner:

    fit <- lm(mpg ~ qsec + am + wt + gear,
              data = mtcars)

    dust(fit, descriptors = c("label", "level_detail"),
         glance_foot = TRUE) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle(rows = 1, border = "top") %>%
      sprinkle(cols = c(2, 6), round = 2, na_string = "",
               part = "foot") %>%
      sprinkle(rows = 1, border = "top", part = "foot") %>%
      sprinkle_print_method("console")

    ##            label         level_detail estimate std.error   statistic p.value
    ## 1    (Intercept)                 <NA>     9.37      8.37        1.12    0.27
    ## 2           <NA> Manual vs. Automatic     3.15      1.94        1.62    0.12
    ## 3           <NA>              4 vs. 3    -0.27      1.66       -0.16    0.87
    ## 4           <NA>              5 vs. 3    -0.27      2.06       -0.13     0.9
    ## 5           <NA>                          1.24      0.38        3.25   0.003
    ## 6           <NA>                         -3.93      0.74       -5.29 < 0.001
    ## 7      r.squared                 0.85                         logLik  -72.04
    ## 8  adj.r.squared                 0.82                            AIC  158.08
    ## 9          sigma                 2.55                            BIC  168.34
    ## 10     statistic                29.43                       deviance   169.1
    ## 11       p.value                    0                    df.residual      26
    ## 12            df                    5                           nobs      32

At times, we may find the volume of these fit statistics overwhelming and may want to display only a subset of them. This can be done with the use of the `glance_stats` argument in `dust`. In addition to selecting the statistics to display, the order in which they are displayed may also be controlled.

    fit <- lm(mpg ~ qsec + am + wt + gear,
              data = mtcars)

    dust(fit, descriptors = c("label", "level_detail"),
         glance_foot = TRUE,
         glance_stats = c("AIC", "adj.r.squared", "BIC", "df"),
         byrow = TRUE) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle(rows = 1, border = "top") %>%
      sprinkle(cols = c(2, 6), round = 2, na_string = "",
               part = "foot") %>%
      sprinkle(rows = 1, border = "top", part = "foot") %>%
      sprinkle_print_method("console")

    ##         label         level_detail estimate std.error     statistic p.value
    ## 1 (Intercept)                 <NA>     9.37      8.37          1.12    0.27
    ## 2        <NA> Manual vs. Automatic     3.15      1.94          1.62    0.12
    ## 3        <NA>              4 vs. 3    -0.27      1.66         -0.16    0.87
    ## 4        <NA>              5 vs. 3    -0.27      2.06         -0.13     0.9
    ## 5        <NA>                          1.24      0.38          3.25   0.003
    ## 6        <NA>                         -3.93      0.74         -5.29 < 0.001
    ## 7         AIC               158.08                    adj.r.squared    0.82
    ## 8         BIC               168.34                               df       5

# 3 Markdown Output

Markdown output will support some of the features of `pixiedust` a little better, but they are still pretty limited. Background colors are not supported. Headers will appear in bold text. To distinguish the footers, we’ll print them in italics.

## 3.1 Multirow Headers and Footers

To illustrate the multirow headers and footers, we will generate a header that has both the column name and the label. The footer will summarise the values in each column by mean and standard deviation.

    custom_head <- rbind(names(mtcars2),
                         labelVector::get_label(mtcars2,
                                                names(mtcars2))) %>%
      as.data.frame(stringsAsFactors = FALSE)

    custom_foot <- rbind(vapply(mtcars2, mean, numeric(1)),
                         vapply(mtcars2, sd, numeric(1))) %>%
      as.data.frame(stringsAsFactors = FALSE)

Now we need only create a `dust` object and add our custom header and footer. To replace components of the `dust` object, we “`redust`” the component. We’ll also shade the head and foot in different shades of gray to make them stand out.

    dust(mtcars2) %>%
      redust(custom_head, part = "head") %>%
      redust(custom_foot, part = "foot") %>%
      sprinkle_table(round = 2) %>%
      sprinkle(bg = "gray", part = "head") %>%
      sprinkle(bg = "lightgray", part = "foot") %>%
      sprinkle_print_method("markdown")

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
21 | 6 | 160 | 110 | 3.9 | 2.62 | 16.46 | 0 | 1 | 4 | 4
21 | 6 | 160 | 110 | 3.9 | 2.88 | 17.02 | 0 | 1 | 4 | 4
22.8 | 4 | 108 | 93 | 3.85 | 2.32 | 18.61 | 1 | 1 | 4 | 1
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.44 | 1 | 0 | 3 | 1
18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17.02 | 0 | 0 | 3 | 2
18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.22 | 1 | 0 | 3 | 1
14.3 | 8 | 360 | 245 | 3.21 | 3.57 | 15.84 | 0 | 0 | 3 | 4
24.4 | 4 | 146.7 | 62 | 3.69 | 3.19 | 20 | 1 | 0 | 4 | 2
22.8 | 4 | 140.8 | 95 | 3.92 | 3.15 | 22.9 | 1 | 0 | 4 | 2
19.2 | 6 | 167.6 | 123 | 3.92 | 3.44 | 18.3 | 1 | 0 | 4 | 4
20.37 | 5.8 | 208.61 | 122.8 | 3.54 | 3.13 | 18.58 | 0.6 | 0.3 | 3.6 | 2.5
2.91 | 1.48 | 90.37 | 51.45 | 0.44 | 0.41 | 2.14 | 0.52 | 0.48 | 0.52 | 1.35

## 3.2 Longtable Feature

The longtable feature is named for the LaTeX package `longtable`, which will automatically break a table into multiple divisions, each of which is displayed on a separate page. We can use the long table sprinkle to break a table into divisions of any size we like. In this example, we’ll use divisions of four rows each. We will use the same header and footer as the previous example, and we’ll also make use of the interfoot, which is the footer placed at the bottom of each intermediate table, while the footer is placed only at the bottom of the last table. We’ll make use of the multi-cell feature for the interfoot here, although we won’t really discuss it until the next section.

The code for this table is nearly identical to the previous example. We just add a `redust` call for the interfoot and add a `longtable` argument to `sprinkle_table`.

    custom_interfoot <- data.frame("To Be Continued",
                                   "", "", "", "", "", "",
                                   "", "", "", "")

    (x <- dust(mtcars2) %>%
      redust(custom_head, part = "head") %>%
      redust(custom_foot, part = "foot") %>%
      redust(custom_interfoot, part = "interfoot") %>%
      sprinkle_table(round = 2, longtable = 4) %>%
      sprinkle(bg = "gray", part = "head") %>%
      sprinkle(bg = "lightgray", part = "foot") %>%
      sprinkle(bg = "lightgray", part = "interfoot") %>%
      sprinkle_print_method("markdown"))

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
21 | 6 | 160 | 110 | 3.9 | 2.62 | 16.46 | 0 | 1 | 4 | 4
21 | 6 | 160 | 110 | 3.9 | 2.88 | 17.02 | 0 | 1 | 4 | 4
22.8 | 4 | 108 | 93 | 3.85 | 2.32 | 18.61 | 1 | 1 | 4 | 1
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.44 | 1 | 0 | 3 | 1
To Be Continued |  |  |  |  |  |  |  |  |  |

| mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
1 | Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
5 | 18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17.02 | 0 | 0 | 3 | 2
6 | 18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.22 | 1 | 0 | 3 | 1
7 | 14.3 | 8 | 360 | 245 | 3.21 | 3.57 | 15.84 | 0 | 0 | 3 | 4
8 | 24.4 | 4 | 146.7 | 62 | 3.69 | 3.19 | 20 | 1 | 0 | 4 | 2
11 | To Be Continued |  |  |  |  |  |  |  |  |  |

| mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
1 | Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
9 | 22.8 | 4 | 140.8 | 95 | 3.92 | 3.15 | 22.9 | 1 | 0 | 4 | 2
10 | 19.2 | 6 | 167.6 | 123 | 3.92 | 3.44 | 18.3 | 1 | 0 | 4 | 4
11 | 20.37 | 5.8 | 208.61 | 122.8 | 3.54 | 3.13 | 18.58 | 0.6 | 0.3 | 3.6 | 2.5
2 | 2.91 | 1.48 | 90.37 | 51.45 | 0.44 | 0.41 | 2.14 | 0.52 | 0.48 | 0.52 | 1.35

## 3.3 Multi-cell Representations

The table above doesn’t look quite right, however, because the “To Be Continued” appears in one cell when it might look better spread out on a single line. With the HTML output, we could use the `merge` sprinkle to merge all of the cells in the `interfoot` in order to make it appear more fluid. However, this feature isn’t supported by markdown, so the best we can get is the text in one cell.

    x %>%
      sprinkle(merge = TRUE, halign = "center", part = "interfoot")

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
21 | 6 | 160 | 110 | 3.9 | 2.62 | 16.46 | 0 | 1 | 4 | 4
21 | 6 | 160 | 110 | 3.9 | 2.88 | 17.02 | 0 | 1 | 4 | 4
22.8 | 4 | 108 | 93 | 3.85 | 2.32 | 18.61 | 1 | 1 | 4 | 1
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.44 | 1 | 0 | 3 | 1
To Be Continued |  |  |  |  |  |  |  |  |  |

| mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
1 | Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
5 | 18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17.02 | 0 | 0 | 3 | 2
6 | 18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.22 | 1 | 0 | 3 | 1
7 | 14.3 | 8 | 360 | 245 | 3.21 | 3.57 | 15.84 | 0 | 0 | 3 | 4
8 | 24.4 | 4 | 146.7 | 62 | 3.69 | 3.19 | 20 | 1 | 0 | 4 | 2
11 | To Be Continued |  |  |  |  |  |  |  |  |  |

| mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
1 | Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
9 | 22.8 | 4 | 140.8 | 95 | 3.92 | 3.15 | 22.9 | 1 | 0 | 4 | 2
10 | 19.2 | 6 | 167.6 | 123 | 3.92 | 3.44 | 18.3 | 1 | 0 | 4 | 4
11 | 20.37 | 5.8 | 208.61 | 122.8 | 3.54 | 3.13 | 18.58 | 0.6 | 0.3 | 3.6 | 2.5
2 | 2.91 | 1.48 | 90.37 | 51.45 | 0.44 | 0.41 | 2.14 | 0.52 | 0.48 | 0.52 | 1.35

The `merge` sprinkle may be used to join any number of conjoined cells. The following example is for illustration only, and probably wouldn’t be put to use in any meaningful application. What we will do is merge nine cells and display the value of the center cell. Take notice of where the value `160` appears in the table below compared to the table above. In the case of markdown output, the cells aren’t actually merged, but the values of the non-displayed cells are set to `""`.

    x %>%
      sprinkle(merge = TRUE, halign = "center", part = "interfoot") %>%
      sprinkle(rows = 1:3, cols = 2:4,
               merge = TRUE, merge_rowval = 2, merge_colval = 3,
               halign = "center")

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
21 |  |  |  | 3.9 | 2.62 | 16.46 | 0 | 1 | 4 | 4
21 |  | 160 |  | 3.9 | 2.88 | 17.02 | 0 | 1 | 4 | 4
22.8 |  |  |  | 3.85 | 2.32 | 18.61 | 1 | 1 | 4 | 1
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.44 | 1 | 0 | 3 | 1
To Be Continued |  |  |  |  |  |  |  |  |  |

| mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
1 | Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
5 | 18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17.02 | 0 | 0 | 3 | 2
6 | 18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.22 | 1 | 0 | 3 | 1
7 | 14.3 | 8 | 360 | 245 | 3.21 | 3.57 | 15.84 | 0 | 0 | 3 | 4
8 | 24.4 | 4 | 146.7 | 62 | 3.69 | 3.19 | 20 | 1 | 0 | 4 | 2
11 | To Be Continued |  |  |  |  |  |  |  |  |  |

| mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
1 | Gas Mileage | Cylinders | Displacement | Horse Power | Rear Axle Ratio | Weight | 1/4 mile time | V/S | Transmission | Forward Gears | Carburetors
9 | 22.8 | 4 | 140.8 | 95 | 3.92 | 3.15 | 22.9 | 1 | 0 | 4 | 2
10 | 19.2 | 6 | 167.6 | 123 | 3.92 | 3.44 | 18.3 | 1 | 0 | 4 | 4
11 | 20.37 | 5.8 | 208.61 | 122.8 | 3.54 | 3.13 | 18.58 | 0.6 | 0.3 | 3.6 | 2.5
2 | 2.91 | 1.48 | 90.37 | 51.45 | 0.44 | 0.41 | 2.14 | 0.52 | 0.48 | 0.52 | 1.35

## 3.4 Model Summaries with Fit Statistics

`pixiedust` offers a few options to help simplify the preparation of model output for tabular display. If you choose to use the `label` functions from the `labelVector` package, these labels can be accessed for the table. Additionally, the levels of factor variables may be printed in a more human-readable format. (note that the `label` functions from the `Hmisc` package may also be used)

    fit <- lm(mpg ~ qsec + factor(am) + wt + factor(gear),
              data = mtcars)

    dust(fit, descriptors = c("label", "level")) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle_print_method("markdown")

label | level | estimate | std.error | statistic | p.value
--- | --- | --- | --- | --- | ---
(Intercept) | NA | 9.37 | 8.37 | 1.12 | 0.27
NA | Manual | 3.15 | 1.94 | 1.62 | 0.12
NA | 4 | -0.27 | 1.66 | -0.16 | 0.87
NA | 5 | -0.27 | 2.06 | -0.13 | 0.9
NA |  | 1.24 | 0.38 | 3.25 | 0.003
NA |  | -3.93 | 0.74 | -5.29 | < 0.001

Or, if we wish to see the reference value of the factors, we can request the `"level_detail"` descriptor.

    dust(fit, descriptors = c("label", "level_detail")) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle_print_method("markdown")

label | level_detail | estimate | std.error | statistic | p.value
--- | --- | --- | --- | --- | ---
(Intercept) | NA | 9.37 | 8.37 | 1.12 | 0.27
NA | Manual vs. Automatic | 3.15 | 1.94 | 1.62 | 0.12
NA | 4 vs. 3 | -0.27 | 1.66 | -0.16 | 0.87
NA | 5 vs. 3 | -0.27 | 2.06 | -0.13 | 0.9
NA |  | 1.24 | 0.38 | 3.25 | 0.003
NA |  | -3.93 | 0.74 | -5.29 | < 0.001

One word of caution: The labels are pulled from the data obtained by `model.frame`, and if you apply a function to a term in your formula, you might lose the label. Consider the example below, where we include the `vs` variable, but convert it from a numeric to a factor. If retaining the label is important to you, making your conversions prior to assigning the labels will be a good habit. Don’t fret too much, however, as you can always replace a cell’s content with the `replace` sprinkle.

    fit <- lm(mpg ~ qsec + am + wt + gear + factor(vs),
              data = mtcars)

    dust(fit, descriptors = c("label", "level_detail")) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle_print_method("markdown")

label | level_detail | estimate | std.error | statistic | p.value
--- | --- | --- | --- | --- | ---
(Intercept) | NA | 9.55 | 9.45 | 1.01 | 0.32
NA | Manual vs. Automatic | 3.17 | 2.01 | 1.58 | 0.13
NA | 1 vs. 0 | 0.09 | 1.92 | 0.05 | 0.96
NA | 4 vs. 3 | -0.29 | 1.77 | -0.17 | 0.87
NA | 5 vs. 3 | -0.29 | 2.17 | -0.14 | 0.89
NA |  | 1.23 | 0.51 | 2.39 | 0.025
NA |  | -3.91 | 0.85 | -4.62 | < 0.001

In addition to providing better labeling of terms and factor levels, `pixiedust` allows you to add model fit statistics in a similar manner that the `stargazer` package does. Under the default settings, we can build these statistics in the following manner:

    fit <- lm(mpg ~ qsec + am + wt + gear,
              data = mtcars)

    dust(fit, descriptors = c("label", "level_detail"),
         glance_foot = TRUE) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle(rows = 1, border = "top") %>%
      sprinkle(cols = c(2, 6), round = 2, na_string = "",
               part = "foot") %>%
      sprinkle(rows = 1, border = "top", part = "foot") %>%
      sprinkle_print_method("markdown")

label | level_detail | estimate | std.error | statistic | p.value
--- | --- | --- | --- | --- | ---
(Intercept) | NA | 9.37 | 8.37 | 1.12 | 0.27
NA | Manual vs. Automatic | 3.15 | 1.94 | 1.62 | 0.12
NA | 4 vs. 3 | -0.27 | 1.66 | -0.16 | 0.87
NA | 5 vs. 3 | -0.27 | 2.06 | -0.13 | 0.9
NA |  | 1.24 | 0.38 | 3.25 | 0.003
NA |  | -3.93 | 0.74 | -5.29 | < 0.001
r.squared | 0.85 |  |  | logLik | -72.04
adj.r.squared | 0.82 |  |  | AIC | 158.08
sigma | 2.55 |  |  | BIC | 168.34
statistic | 29.43 |  |  | deviance | 169.1
p.value | 0 |  |  | df.residual | 26
df | 5 |  |  | nobs | 32

At times, we may find the volume of these fit statistics overwhelming and may want to display only a subset of them. This can be done with the use of the `glance_stats` argument in `dust`. In addition to selecting the statistics to display, the order in which they are displayed may also be controlled.

    fit <- lm(mpg ~ qsec + am + wt + gear,
              data = mtcars)

    dust(fit, descriptors = c("label", "level_detail"),
         glance_foot = TRUE,
         glance_stats = c("AIC", "adj.r.squared", "BIC", "df"),
         byrow = TRUE) %>%
      sprinkle(cols = 3:5, round = 2) %>%
      sprinkle(cols = 6, fn = quote(pvalString(value))) %>%
      sprinkle(rows = 1, border = "top") %>%
      sprinkle(cols = c(2, 6), round = 2, na_string = "",
               part = "foot") %>%
      sprinkle(rows = 1, border = "top", part = "foot") %>%
      sprinkle_print_method("markdown")

label | level_detail | estimate | std.error | statistic | p.value
--- | --- | --- | --- | --- | ---
(Intercept) | NA | 9.37 | 8.37 | 1.12 | 0.27
NA | Manual vs. Automatic | 3.15 | 1.94 | 1.62 | 0.12
NA | 4 vs. 3 | -0.27 | 1.66 | -0.16 | 0.87
NA | 5 vs. 3 | -0.27 | 2.06 | -0.13 | 0.9
NA |  | 1.24 | 0.38 | 3.25 | 0.003
NA |  | -3.93 | 0.74 | -5.29 | < 0.001
AIC | 158.08 |  |  | adj.r.squared | 0.82
BIC | 168.34 |  |  | df | 5