Using Skimr

Elin Waring

2018-04-02

skimr is designed to provide summary statistics about variables. It is opinionated in its defaults, but easy to modify.

In base R, the most similar functions are summary() for vectors and data frames and fivenum() for numeric vectors:

summary(iris)
##   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
##  Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100  
##  1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300  
##  Median :5.800   Median :3.000   Median :4.350   Median :1.300  
##  Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199  
##  3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800  
##  Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500  
##        Species  
##  setosa    :50  
##  versicolor:50  
##  virginica :50  
##                 
##                 
## 
summary(iris$Sepal.Length)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   4.300   5.100   5.800   5.843   6.400   7.900
fivenum(iris$Sepal.Length)
## [1] 4.3 5.1 5.8 6.4 7.9
summary(iris$Species)
##     setosa versicolor  virginica 
##         50         50         50

The skim function

The core function of skimr is skim(). skim() is a S3 generic function, with methods for data frames, grouped data frames and vectors. Like summary(), skim()’s method for data frames presents results for every column; the statistics it provides depend on the class of the variable.

Skimming data frames

By design, the main focus of skimr is on data frames; it is intended to fit well withiin a data pipeline and relies extensively on tidyverse vocabulary, which focuses on data frames.

Results of skim() are printed horizontally, with one section per variable type and one row per variable. Results are returned from skim() as a long tibble of class skim_df, with one row per variable + summary statistic.

library(skimr)
skim(iris)
## Skim summary statistics
##  n obs: 150 
##  n variables: 5 
## 
## Variable type: factor 
##  variable missing complete   n n_unique                       top_counts
##   Species       0      150 150        3 set: 50, ver: 50, vir: 50, NA: 0
##  ordered
##    FALSE
## 
## Variable type: numeric 
##      variable missing complete   n mean   sd  p0 p25  p50 p75 p100
##  Petal.Length       0      150 150 3.76 1.77 1   1.6 4.35 5.1  6.9
##   Petal.Width       0      150 150 1.2  0.76 0.1 0.3 1.3  1.8  2.5
##  Sepal.Length       0      150 150 5.84 0.83 4.3 5.1 5.8  6.4  7.9
##   Sepal.Width       0      150 150 3.06 0.44 2   2.8 3    3.3  4.4
##      hist
##  ▇▁▁▂▅▅▃▁
##  ▇▁▁▅▃▃▂▂
##  ▂▇▅▇▆▅▂▂
##  ▁▂▅▇▃▂▁▁

This is in contrast to summary.data.frame(), which stores statistics in a table. The distinction is important, because the skim_df object is pipeable and easy to use for additional manipulation: for example, the user could select all of the variable means, or all summary statistics for a specific variable.

skim(iris) %>%
  dplyr::filter(stat == "mean")
## # A tibble: 4 x 6
##   variable     type    stat  level value formatted
##   <chr>        <chr>   <chr> <chr> <dbl> <chr>    
## 1 Sepal.Length numeric mean  .all   5.84 5.84     
## 2 Sepal.Width  numeric mean  .all   3.06 3.06     
## 3 Petal.Length numeric mean  .all   3.76 3.76     
## 4 Petal.Width  numeric mean  .all   1.20 1.2

The skim_df object always contains 6 columns:

s <- skim(iris)
head(s, 15)
## # A tibble: 15 x 6
##    variable     type    stat     level   value formatted
##    <chr>        <chr>   <chr>    <chr>   <dbl> <chr>    
##  1 Sepal.Length numeric missing  .all    0.    0        
##  2 Sepal.Length numeric complete .all  150.    150      
##  3 Sepal.Length numeric n        .all  150.    150      
##  4 Sepal.Length numeric mean     .all    5.84  5.84     
##  5 Sepal.Length numeric sd       .all    0.828 0.83     
##  6 Sepal.Length numeric p0       .all    4.30  4.3      
##  7 Sepal.Length numeric p25      .all    5.10  5.1      
##  8 Sepal.Length numeric p50      .all    5.80  5.8      
##  9 Sepal.Length numeric p75      .all    6.40  6.4      
## 10 Sepal.Length numeric p100     .all    7.90  7.9      
## 11 Sepal.Length numeric hist     .all   NA     ▂▇▅▇▆▅▂▂ 
## 12 Sepal.Width  numeric missing  .all    0.    0        
## 13 Sepal.Width  numeric complete .all  150.    150      
## 14 Sepal.Width  numeric n        .all  150.    150      
## 15 Sepal.Width  numeric mean     .all    3.06  3.06

skim() also supports grouped data. In this case, one additional column for each grouping variable is added to the skim_df object.

mtcars %>%
  dplyr::group_by(gear) %>%
  skim()
## Skim summary statistics
##  n obs: 32 
##  n variables: 11 
##  group variables: gear 
## 
## Variable type: numeric 
##  gear variable missing complete  n   mean     sd     p0    p25    p50
##     3       am       0       15 15   0      0      0      0      0   
##     3     carb       0       15 15   2.67   1.18   1      2      3   
##     3      cyl       0       15 15   7.47   1.19   4      8      8   
##     3     disp       0       15 15 326.3   94.85 120.1  275.8  318   
##     3     drat       0       15 15   3.13   0.27   2.76   3.04   3.08
##     3       hp       0       15 15 176.13  47.69  97    150    180   
##     3      mpg       0       15 15  16.11   3.37  10.4   14.5   15.5 
##     3     qsec       0       15 15  17.69   1.35  15.41  17.04  17.42
##     3       vs       0       15 15   0.2    0.41   0      0      0   
##     3       wt       0       15 15   3.89   0.83   2.46   3.45   3.73
##     4       am       0       12 12   0.67   0.49   0      0      1   
##     4     carb       0       12 12   2.33   1.3    1      1      2   
##     4      cyl       0       12 12   4.67   0.98   4      4      4   
##     4     disp       0       12 12 123.02  38.91  71.1   78.92 130.9 
##     4     drat       0       12 12   4.04   0.31   3.69   3.9    3.92
##     4       hp       0       12 12  89.5   25.89  52     65.75  94   
##     4      mpg       0       12 12  24.53   5.28  17.8   21     22.8 
##     4     qsec       0       12 12  18.96   1.61  16.46  18.46  18.75
##     4       vs       0       12 12   0.83   0.39   0      1      1   
##     4       wt       0       12 12   2.62   0.63   1.61   2.13   2.7 
##     5       am       0        5  5   1      0      1      1      1   
##     5     carb       0        5  5   4.4    2.61   2      2      4   
##     5      cyl       0        5  5   6      2      4      4      6   
##     5     disp       0        5  5 202.48 115.49  95.1  120.3  145   
##     5     drat       0        5  5   3.92   0.39   3.54   3.62   3.77
##     5       hp       0        5  5 195.6  102.83  91    113    175   
##     5      mpg       0        5  5  21.38   6.66  15     15.8   19.7 
##     5     qsec       0        5  5  15.64   1.13  14.5   14.6   15.5 
##     5       vs       0        5  5   0.2    0.45   0      0      0   
##     5       wt       0        5  5   2.63   0.82   1.51   2.14   2.77
##     p75   p100     hist
##    0      0    ▁▁▁▇▁▁▁▁
##    4      4    ▅▁▆▁▁▅▁▇
##    8      8    ▁▁▁▁▁▁▁▇
##  380    472    ▂▁▂▇▃▆▂▆
##    3.18   3.73 ▃▃▇▆▁▁▁▃
##  210    245    ▅▁▃▁▇▂▂▅
##   18.4   21.5  ▃▁▃▇▃▃▂▃
##   17.99  20.22 ▃▁▆▇▆▁▂▃
##    0      1    ▇▁▁▁▁▁▁▂
##    3.96   5.42 ▁▁▇▅▁▁▁▃
##    1      1    ▃▁▁▁▁▁▁▇
##    4      4    ▇▁▇▁▁▁▁▇
##    6      6    ▇▁▁▁▁▁▁▃
##  160    167.6  ▇▁▁▂▂▂▂▇
##    4.09   4.93 ▁▇▃▁▁▁▁▁
##  110    123    ▂▇▁▁▃▁▆▃
##   28.08  33.9  ▅▇▅▂▂▁▂▅
##   19.58  22.9  ▃▁▇▆▃▁▁▂
##    1      1    ▂▁▁▁▁▁▁▇
##    3.16   3.44 ▇▃▃▃▃▇▇▇
##    1      1    ▁▁▁▇▁▁▁▁
##    6      8    ▇▁▃▁▁▃▁▃
##    8      8    ▇▁▁▃▁▁▁▇
##  301    351    ▇▃▁▁▁▁▃▃
##    4.22   4.43 ▇▁▃▁▁▁▃▃
##  264    335    ▇▁▃▁▁▃▁▃
##   26     30.4  ▇▁▃▁▁▃▁▃
##   16.7   16.9  ▇▁▁▃▁▁▁▇
##    0      1    ▇▁▁▁▁▁▁▂
##    3.17   3.57 ▇▁▇▁▇▁▇▇

Individual columns from a data frame may be selected using tidyverse-style selectors.

skim(iris, Sepal.Length, Species)
## Skim summary statistics
##  n obs: 150 
##  n variables: 5 
## 
## Variable type: factor 
##  variable missing complete   n n_unique                       top_counts
##   Species       0      150 150        3 set: 50, ver: 50, vir: 50, NA: 0
##  ordered
##    FALSE
## 
## Variable type: numeric 
##      variable missing complete   n mean   sd  p0 p25 p50 p75 p100     hist
##  Sepal.Length       0      150 150 5.84 0.83 4.3 5.1 5.8 6.4  7.9 ▂▇▅▇▆▅▂▂
skim(iris, starts_with("Sepal"))
## Skim summary statistics
##  n obs: 150 
##  n variables: 5 
## 
## Variable type: numeric 
##      variable missing complete   n mean   sd  p0 p25 p50 p75 p100     hist
##  Sepal.Length       0      150 150 5.84 0.83 4.3 5.1 5.8 6.4  7.9 ▂▇▅▇▆▅▂▂
##   Sepal.Width       0      150 150 3.06 0.44 2   2.8 3   3.3  4.4 ▁▂▅▇▃▂▁▁

If an individual column is of an unsuppported class, it is treated as a character variable with a warning.

Skimming vectors

skim() also handles individual vectors that are not part of a data frame. For example, the lynx data set is class ts.

skim(datasets::lynx)
## Skim summary statistics
## 
## Variable type: ts 
##        variable missing complete   n start  end frequency deltat    mean
##  datasets::lynx       0      114 114  1821 1934         1      1 1538.02
##       sd min  max median line_graph
##  1585.84  39 6991    771   ⡈⢄⡠⢁⣀⠒⣀⠔

If you attempt to use skim() on a class that does not have support, it will coerce it to character (with a warning) and report number of NAs; number complete (non-missing); number of rows; number empty strings (i.e. “”); minimum and maximum lengths of non-empty strings; and number of unique values.

lynx <- datasets::lynx
class(lynx) <- "unknown_class"
skim(lynx)
## Warning: No summary functions for vectors of class: unknown_class.
## Coercing to character
## Skim summary statistics
## 
## Variable type: character 
##  variable missing complete   n min max empty n_unique
##      lynx       0      114 114   2   4     0      110

Skimming matrices

skimr does not include a skim.matrix function in order to preserve the ability to handle matrices in flexible ways (in contrast to summary.matrix()). Three possible ways to handle matrices with skim() parallel the three variations of the mean function for matrices.

m <- matrix(c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), nrow = 4, ncol = 3)
m
##      [,1] [,2] [,3]
## [1,]    1    5    9
## [2,]    2    6   10
## [3,]    3    7   11
## [4,]    4    8   12
colMeans(m)
## [1]  2.5  6.5 10.5
rowMeans(m)
## [1] 5 6 7 8
mean(m)
## [1] 6.5
skim(as.data.frame(m))    # Similar to summary.matrix and colMeans()
## Skim summary statistics
##  n obs: 4 
##  n variables: 3 
## 
## Variable type: numeric 
##  variable missing complete n mean   sd p0  p25  p50   p75 p100     hist
##        V1       0        4 4  2.5 1.29  1 1.75  2.5  3.25    4 ▇▁▇▁▁▇▁▇
##        V2       0        4 4  6.5 1.29  5 5.75  6.5  7.25    8 ▇▁▇▁▁▇▁▇
##        V3       0        4 4 10.5 1.29  9 9.75 10.5 11.25   12 ▇▁▇▁▁▇▁▇
skim(as.data.frame(t(m))) # Similar to rowMeans()
## Skim summary statistics
##  n obs: 3 
##  n variables: 4 
## 
## Variable type: numeric 
##  variable missing complete n mean sd p0 p25 p50 p75 p100     hist
##        V1       0        3 3    5  4  1   3   5   7    9 ▇▁▁▇▁▁▁▇
##        V2       0        3 3    6  4  2   4   6   8   10 ▇▁▁▇▁▁▁▇
##        V3       0        3 3    7  4  3   5   7   9   11 ▇▁▁▇▁▁▁▇
##        V4       0        3 3    8  4  4   6   8  10   12 ▇▁▁▇▁▁▁▇
skim(c(m))                # Similar to mean()
## Skim summary statistics
## 
## Variable type: numeric 
##  variable missing complete  n mean   sd p0  p25 p50  p75 p100     hist
##      c(m)       0       12 12  6.5 3.61  1 3.75 6.5 9.25   12 ▇▃▇▃▃▇▃▇

You can skim a single row or column in the same way as any vector.

skim(m[,1])
## Skim summary statistics
## 
## Variable type: numeric 
##  variable missing complete n mean   sd p0  p25 p50  p75 p100     hist
##    m[, 1]       0        4 4  2.5 1.29  1 1.75 2.5 3.25    4 ▇▁▇▁▁▇▁▇
skim(m[1,])
## Skim summary statistics
## 
## Variable type: numeric 
##  variable missing complete n mean sd p0 p25 p50 p75 p100     hist
##    m[1, ]       0        3 3    5  4  1   3   5   7    9 ▇▁▁▇▁▁▁▇

Alternatives to skim()

skim() for a data frame returns a long, six-column data frame. This long data frame is printed horizontally as a separate summary for each data type found in the data frame, but the object itself is not transformed during the print.

Three other functions are available that may prove useful as part of skim() workflows:

iris_setosa <- iris %>%
  skim_tee(iris) %>%
  dplyr::filter(Species == "setosa")
## Skim summary statistics
##  n obs: 150 
##  n variables: 5 
## 
## Variable type: factor 
##  variable missing complete   n n_unique                       top_counts
##   Species       0      150 150        3 set: 50, ver: 50, vir: 50, NA: 0
##  ordered
##    FALSE
## 
## Variable type: numeric 
##      variable missing complete   n mean   sd  p0 p25  p50 p75 p100
##  Petal.Length       0      150 150 3.76 1.77 1   1.6 4.35 5.1  6.9
##   Petal.Width       0      150 150 1.2  0.76 0.1 0.3 1.3  1.8  2.5
##  Sepal.Length       0      150 150 5.84 0.83 4.3 5.1 5.8  6.4  7.9
##   Sepal.Width       0      150 150 3.06 0.44 2   2.8 3    3.3  4.4
##      hist
##  ▇▁▁▂▅▅▃▁
##  ▇▁▁▅▃▃▂▂
##  ▂▇▅▇▆▅▂▂
##  ▁▂▅▇▃▂▁▁
iris %>% skim_to_list()
## $factor
## # A tibble: 1 x 7
##   variable missing complete n     n_unique top_counts              ordered
## * <chr>    <chr>   <chr>    <chr> <chr>    <chr>                   <chr>  
## 1 Species  0       150      150   3        set: 50, ver: 50, vir:… FALSE  
## 
## $numeric
## # A tibble: 4 x 12
##   variable     missing complete n     mean   sd    p0    p25   p50   p75  
## * <chr>        <chr>   <chr>    <chr> <chr>  <chr> <chr> <chr> <chr> <chr>
## 1 Petal.Length 0       150      150   3.76   1.77  "1  " 1.6   4.35  5.1  
## 2 Petal.Width  0       150      150   "1.2 " 0.76  0.1   0.3   "1.3… 1.8  
## 3 Sepal.Length 0       150      150   5.84   0.83  4.3   5.1   "5.8… 6.4  
## 4 Sepal.Width  0       150      150   3.06   0.44  "2  " 2.8   "3  … 3.3  
## # ... with 2 more variables: p100 <chr>, hist <chr>
iris_skimmed <- iris %>% skim_to_list()
iris_skimmed[["numeric"]] %>% dplyr::select(mean, sd)
## # A tibble: 4 x 2
##   mean   sd   
## * <chr>  <chr>
## 1 3.76   1.77 
## 2 "1.2 " 0.76 
## 3 5.84   0.83 
## 4 3.06   0.44
iris %>% skim_to_wide(iris)
## # A tibble: 5 x 16
##   type   variable missing complete n     n_unique top_counts ordered mean 
##   <chr>  <chr>    <chr>   <chr>    <chr> <chr>    <chr>      <chr>   <chr>
## 1 factor Species  0       150      150   3        set: 50, … FALSE   <NA> 
## 2 numer… Petal.L… 0       150      150   <NA>     <NA>       <NA>    3.76 
## 3 numer… Petal.W… 0       150      150   <NA>     <NA>       <NA>    "1.2…
## 4 numer… Sepal.L… 0       150      150   <NA>     <NA>       <NA>    5.84 
## 5 numer… Sepal.W… 0       150      150   <NA>     <NA>       <NA>    3.06 
## # ... with 7 more variables: sd <chr>, p0 <chr>, p25 <chr>, p50 <chr>,
## #   p75 <chr>, p100 <chr>, hist <chr>

Modifying skim() with skim_with() and skim_with_defaults()

skimr is opinionated in its choice of defaults, but users can easily add to, replace, or remove the statistics for a class.

To add a statistic, create a named list for each class using the format below:

classname = list(mad_name = mad)
skim_with(numeric = list(mad_name = mad))
skim(datasets::chickwts)
## Skim summary statistics
##  n obs: 71 
##  n variables: 2 
## 
## Variable type: factor 
##  variable missing complete  n n_unique                         top_counts
##      feed       0       71 71        6 soy: 14, cas: 12, lin: 12, sun: 12
##  ordered
##    FALSE
## 
## Variable type: numeric 
##  variable missing complete  n   mean    sd  p0   p25 p50   p75 p100
##    weight       0       71 71 261.31 78.07 108 204.5 258 323.5  423
##      hist mad_name
##  ▃▅▅▇▃▇▂▂    91.92

When skim_with() is used to modify the statistics, the new list(s) of statistics remains in place until they are reset using skim_with_defaults().

By default skim_with() appends the new statistics, but setting append = FALSE replaces the defaults.

skim_with_defaults()
skim_with(numeric = list(mad_name = mad), append = FALSE)
skim(datasets::chickwts)
## Skim summary statistics
##  n obs: 71 
##  n variables: 2 
## 
## Variable type: factor 
##  variable missing complete  n n_unique                         top_counts
##      feed       0       71 71        6 soy: 14, cas: 12, lin: 12, sun: 12
##  ordered
##    FALSE
## 
## Variable type: numeric 
##  variable mad_name
##    weight    91.92
skim_with_defaults() # Reset to defaults

You can also use skim_with() to remove specific statistics by setting them to NULL.

skim_with(numeric = list(hist = NULL))
skim(datasets::chickwts)
## Skim summary statistics
##  n obs: 71 
##  n variables: 2 
## 
## Variable type: factor 
##  variable missing complete  n n_unique                         top_counts
##      feed       0       71 71        6 soy: 14, cas: 12, lin: 12, sun: 12
##  ordered
##    FALSE
## 
## Variable type: numeric 
##  variable missing complete  n   mean    sd  p0   p25 p50   p75 p100
##    weight       0       71 71 261.31 78.07 108 204.5 258 323.5  423
skim_with_defaults()

Formatting individual values

When printing, skimr formats displayed statistics in an opinionated way; these values are stored in the formatted column of the skim_df object and are always character. skim() attempts to use a reasonable number of decimal places for calculated values based on the data type (integer or numeric) and number of stored decimals. For statistics such as p0 and p100, the actual stored values are displayed. Decimals in a column are aligned. Date formats are used for date statistics.

Users can override these opinionated formats using skim_format(). show_formats() will display the current options in use for each data type. Using skim_format_defaults() will reset the formats to their default settings.

Rendering the results of skim()

The skim_df object is a long data frame with one row for each combination of variable and statistic (and optionally for group). The horizontal display is created by default using print.skim_df(); users can specify additional options by explicitly calling print([skim_df object], ...).

skim_df() objects can also be rendered using kable() and pander(). These both provide more control over the rendered results, particularly when used in conjunction with knitr. Documentation of these options is covered in more detail in the knitr package for kable() and the pander package for pander(). Using either of these may require use of document or chunk options and fonts, including a chunk option of results = 'asis'. This topic is addressed in more detail in the Using Fonts vignette. Because of the complexity of this, the samples below are shown as they would be in the console.

skim(iris) %>% skimr::kable()
## Skim summary statistics  
##  n obs: 150    
##  n variables: 5    
## 
## Variable type: factor
## 
## variable   missing   complete   n     n_unique   top_counts                         ordered 
## ---------  --------  ---------  ----  ---------  ---------------------------------  --------
## Species    0         150        150   3          set: 50, ver: 50, vir: 50, NA: 0   FALSE   
## 
## Variable type: numeric
## 
## variable       missing   complete   n     mean   sd     p0    p25   p50    p75   p100   hist     
## -------------  --------  ---------  ----  -----  -----  ----  ----  -----  ----  -----  ---------
## Petal.Length   0         150        150   3.76   1.77   1     1.6   4.35   5.1   6.9    ▇▁▁▂▅▅▃▁ 
## Petal.Width    0         150        150   1.2    0.76   0.1   0.3   1.3    1.8   2.5    ▇▁▁▅▃▃▂▂ 
## Sepal.Length   0         150        150   5.84   0.83   4.3   5.1   5.8    6.4   7.9    ▂▇▅▇▆▅▂▂ 
## Sepal.Width    0         150        150   3.06   0.44   2     2.8   3      3.3   4.4    ▁▂▅▇▃▂▁▁
library(pander)
panderOptions('knitr.auto.asis', FALSE)
skim(iris) %>% pander() 
## Skim summary statistics  
##    n obs: 150    
##  n variables: 5    
## 
## ------------------------------------------------
##  variable   missing   complete    n    n_unique 
## ---------- --------- ---------- ----- ----------
##  Species       0        150      150      3     
## ------------------------------------------------
## 
## Table: Table continues below
## 
##  
## ------------------------------------------
##            top_counts             ordered 
## -------------------------------- ---------
##  set: 50, ver: 50, vir: 50, NA:    FALSE  
##                0                          
## ------------------------------------------
## 
## 
## --------------------------------------------------------------------------------
##    variable     missing   complete    n    mean    sd    p0    p25   p50    p75 
## -------------- --------- ---------- ----- ------ ------ ----- ----- ------ -----
##  Petal.Length      0        150      150   3.76   1.77    1    1.6   4.35   5.1 
## 
##  Petal.Width       0        150      150   1.2    0.76   0.1   0.3   1.3    1.8 
## 
##  Sepal.Length      0        150      150   5.84   0.83   4.3   5.1   5.8    6.4 
## 
##  Sepal.Width       0        150      150   3.06   0.44    2    2.8    3     3.3 
## --------------------------------------------------------------------------------
## 
## Table: Table continues below
## 
##  
## -----------------
##  p100     hist   
## ------ ----------
##  6.9    ▇▁▁▂▅▅▃▁ 
## 
##  2.5    ▇▁▁▅▃▃▂▂ 
## 
##  7.9    ▂▇▅▇▆▅▂▂ 
## 
##  4.4    ▁▂▅▇▃▂▁▁ 
## -----------------

Solutions to common rendering problems

The details of rendering are dependent on the operating system R is running on, the locale of the installation, and the fonts installed. Rendering may also differ based on whether it occurs in the console or when knitting to specific types of documents such as HTML and PDF.

The most commonly reported problems involve rendering the spark graphs (inline histogram). Currently pander() does not support inline_histograms on Windows. Also, Windows does not support sparkline graphs.

In order to render the sparkgraphs in html or PDF histogram you may need to change fonts to one that supports blocks or Braille (depending on which you need). Please review the separate vignette and associated template for details.