1 Quick start

(Please note that the HTML colors below are only approximate rendering of how the output will look on a terminal).

data(starwars)
sw <- starwars[, c(1:4, 7:8)]
sw %>% colorDF
Color data frame 6 x 87:
(Showing rows 1 - 20 out of 87)
  │name                 │height│mass│hair_color   │birth_year│gender       
 1Luke Skywalker          172  77blond                19male         
 2C-3PO                   167  75NA                  112NA           
 3R2-D2                    96  32NA                   33NA           
 4Darth Vader             202 136none                 42male         
 5Leia Organa             150  49brown                19female       
 6Owen Lars               178 120brown, grey          52male         
 7Beru Whitesun lars      165  75brown                47female       
 8R5-D4                    97  32NA                   NANA           
 9Biggs Darklighter       183  84black                24male         
10Obi-Wan Kenobi          182  77auburn, white        57male         
11Anakin Skywalker        188  84blond                42male         
12Wilhuff Tarkin          180  NAauburn, grey         64male         
13Chewbacca               228 112brown               200male         
14Han Solo                180  80brown                29male         
15Greedo                  173  74NA                   44male         
16Jabba Desilijic Tiure   1751358NA                  600hermaphrodite
17Wedge Antilles          170  77brown                21male         
18Jek Tono Porkins        180 110brown                NAmale         
19Yoda                     66  17white               896male         
20Palpatine               170  75grey                 82male         
as.colorDF(sw) %>% summary
Color data frame 5 x 6:
 │Col       │Class    │NAs│unique
1name      character  0    87
2height    integer    6    46
3mass      numeric   28    39
4hair_colorcharacter  5    13
5birth_yearnumeric   44    37
6gender    character  3     5

 │Summary                                                           
1All values unique                                                 
2 66 [167 <180> 191] 264                                           
3  15 [  56 <  79>   84] 1358                                      
4none: 37, brown: 18, black: 13, white: 4, blond: 3, auburn: 1, ...
5  8 [ 35 < 52>  72] 896                                           
6male: 62, female: 19, none: 2, hermaphrodite: 1                   

2 Colorful data frames

Your average terminal in which you run R is capable of displaying colors, styles and unicode characters. Wouldn’t it be nice to add some color to the data frames you are displaying? For example, that factors are shown in a distinct color (no confusing of strings and factors any more!) or that significant p-values are colored in red?

This was my motivation when writing this tiny package. Of course, changing default method for printing data frames is nothing a package is allowed to do (but read on!). However, this package defines everything you need to get dynamic, colorful output when viewing data frames. There are two things about colorDF which are important:

  1. colorDF never modifies the behavior of the data frame like object or its contents. The only two things that change are (i) the default print method (visualization), and (ii) the “.style” attribute of the object, and that only if you really change the class of the object, which is usually unnecessary.
  2. Any data frame like object can be used in colorDF, and you don’t need to modify these objects to use the colorful visualizations.

Yes, you can color any object that can be cast into a data frame with this or related functions! For example, you can apply it to both tibbles and data.table objects:

## works with standard data.frames
colorDF(mtcars)

## works with tidyverse tibbles
mtcars %>% as_tibble %>% colorDF

## works with data.table
colorDF(data.table(mtcars))

The output of these three commands is identical:

Color data frame 11 x 32:
(Showing rows 1 - 20 out of 32)
                   │mpg│cyl│disp│hp │drat│wt │qsec│vs│am│gear│carb
          Mazda RX4 21  6 160110 3.92.6  16 0 1   4   4
      Mazda RX4 Wag 21  6 160110 3.92.9  17 0 1   4   4
         Datsun 710 23  4 108 93 3.92.3  19 1 1   4   1
     Hornet 4 Drive 21  6 258110 3.13.2  19 1 0   3   1
  Hornet Sportabout 19  8 360175 3.13.4  17 0 0   3   2
            Valiant 18  6 225105 2.83.5  20 1 0   3   1
         Duster 360 14  8 360245 3.23.6  16 0 0   3   4
          Merc 240D 24  4 147 62 3.73.2  20 1 0   4   2
           Merc 230 23  4 141 95 3.93.1  23 1 0   4   2
           Merc 280 19  6 168123 3.93.4  18 1 0   4   4
          Merc 280C 18  6 168123 3.93.4  19 1 0   4   4
         Merc 450SE 16  8 276180 3.14.1  17 0 0   3   3
         Merc 450SL 17  8 276180 3.13.7  18 0 0   3   3
        Merc 450SLC 15  8 276180 3.13.8  18 0 0   3   3
 Cadillac Fleetwood 10  8 472205 2.95.2  18 0 0   3   4
Lincoln Continental 10  8 460215 3.05.4  18 0 0   3   4
  Chrysler Imperial 15  8 440230 3.25.3  17 0 0   3   4
           Fiat 128 32  4  79 66 4.12.2  19 1 1   4   1
        Honda Civic 30  4  76 52 4.91.6  19 1 1   4   2
     Toyota Corolla 34  4  71 65 4.21.8  20 1 1   4   1

3 Column types

Column types are mostly like classes, but colorDF introduces some additional distinctions, specifically “identifier” (such that character columns which contain identifiers can be shown with a particular, distinct style) and “pval”, to show significant p-values in a different color (and use format.pval() for formatting).

colorDF tries to guess how each column should be displayed. First of all, it determines the class of the column (character, integer, numeric, logical, factor). Next, it looks up whether it can guess the contents of the column by looking at the column name (ID, p-value). Finally, it checks whether any columns have been implicitely been assigned a column type.

To assign a particular column type, you need first to turn a data frame colorful and then modify the column type:

sw <- sw %>% as.colorDF
col_type(sw, "name") <- "identifier"
col_type(sw, "gender") <- "factor"
sw$probability <- runif(nrow(sw), 0, 0.1)
col_type(sw, "probability") <- "pval"
sw
Color data frame 7 x 87:
(Showing rows 1 - 20 out of 87)
  │name                 │height│mass│hair_color   │birth_year│gender       
 1       Luke Skywalker   172  77blond                19male         
 2                C-3PO   167  75NA                  112NA           
 3                R2-D2    96  32NA                   33NA           
 4          Darth Vader   202 136none                 42male         
 5          Leia Organa   150  49brown                19female       
 6            Owen Lars   178 120brown, grey          52male         
 7   Beru Whitesun lars   165  75brown                47female       
 8                R5-D4    97  32NA                   NANA           
 9    Biggs Darklighter   183  84black                24male         
10       Obi-Wan Kenobi   182  77auburn, white        57male         
11     Anakin Skywalker   188  84blond                42male         
12       Wilhuff Tarkin   180  NAauburn, grey         64male         
13            Chewbacca   228 112brown               200male         
14             Han Solo   180  80brown                29male         
15               Greedo   173  74NA                   44male         
16Jabba Desilijic Tiure   1751358NA                  600hermaphrodite
17       Wedge Antilles   170  77brown                21male         
18     Jek Tono Porkins   180 110brown                NAmale         
19                 Yoda    66  17white               896male         
20            Palpatine   170  75grey                 82male         

  │probability
 10.09100    
 20.04949    
 30.03106    
 40.07788    
 50.05289    
 60.02460    
 70.04182    
 80.04714    
 90.02727    
100.04489    
110.06712    
120.00054    
130.05606    
140.01441    
150.04311    
160.00457    
170.08491    
180.01783    
190.07835    
200.09416    

Note that changing the column type does not change the class in the data frame! colorDF never touches the data frame object itself, the only operations concern the “.style” attribute. So while you may set a column type to “character” instead of “factor”, it will be looking like a character type on the terminal output, but the column class will still be a factor.

4 Styles and Themes

I am a bit confused when it comes to distinguishing the two. Themes are basically internally predefined styles. Styles are simply lists that hold information how different columns, column and row headers, separators between the columns and highlighted rows are displayed.

Themes can be set using the options(colorDF_theme="<theme name>") command or by directly specifying the option in a call to colorDF:

colorDF(sw, theme="bw")
Color data frame 7 x 87:
(Showing rows 1 - 20 out of 87)
  │name                 │height│mass│hair_color   │birth_year│gender       
 1       Luke Skywalker   172  77blond                19male         
 2                C-3PO   167  75NA                  112NA           
 3                R2-D2    96  32NA                   33NA           
 4          Darth Vader   202 136none                 42male         
 5          Leia Organa   150  49brown                19female       
 6            Owen Lars   178 120brown, grey          52male         
 7   Beru Whitesun lars   165  75brown                47female       
 8                R5-D4    97  32NA                   NANA           
 9    Biggs Darklighter   183  84black                24male         
10       Obi-Wan Kenobi   182  77auburn, white        57male         
11     Anakin Skywalker   188  84blond                42male         
12       Wilhuff Tarkin   180  NAauburn, grey         64male         
13            Chewbacca   228 112brown               200male         
14             Han Solo   180  80brown                29male         
15               Greedo   173  74NA                   44male         
16Jabba Desilijic Tiure   1751358NA                  600hermaphrodite
17       Wedge Antilles   170  77brown                21male         
18     Jek Tono Porkins   180 110brown                NAmale         
19                 Yoda    66  17white               896male         
20            Palpatine   170  75grey                 82male         

  │probability
 10.09100    
 20.04949    
 30.03106    
 40.07788    
 50.05289    
 60.02460    
 70.04182    
 80.04714    
 90.02727    
100.04489    
110.06712    
120.00054    
130.05606    
140.01441    
150.04311    
160.00457    
170.08491    
180.01783    
190.07835    
200.09416    

Here is an overview of the themes. Some of them are intended for dark background and will not look great below:

colorDF_themes_show()
Theme universal - Suitable for all terminals:
Color data frame 7 x 2:
 │ID │String│Factor│Number│Integer│Logical│Pvalue
1ID1foo   foo     12.1     12TRUE   0.001 
2ID2baz   baz     -3.1    -13FALSE  │0.314 


Theme light - Suitable for black on white terminals:
Color data frame 7 x 2:
 │ID │String│Factor│Number│Integer│Logical│Pvalue
1ID1foo   foo     12.1     12TRUE   0.001 
2ID2baz   baz     -3.1    -13FALSE  0.314 


Theme dark - Suitable for white on black terminals:
Color data frame 7 x 2:
 │ID │String│Factor│Number│Integer│Logical│Pvalue
1ID1foo   foo     12.1     12TRUE   0.001 
2ID2baz   baz     -3.1    -13FALSE  0.314 


Theme bw - Black and white only. Suitable for black on white terminals:
Color data frame 7 x 2:
 │ID │String│Factor│Number│Integer│Logical│Pvalue
1ID1│foo   │foo   │  12.1│     12│TRUE   0.001 
2ID2│baz   │baz   │  -3.1│    -13│FALSE  0.314 


Theme wb - Black and white only. Suitable for white on black terminals:
Color data frame 7 x 2:
 │ID │String│Factor│Number│Integer│Logical│Pvalue
1ID1│foo   │foo   │  12.1│     12│TRUE   0.001 
2ID2│baz   │baz   │  -3.1│    -13│FALSE  0.314 


Default theme: light
Change it with `options(colorDF_theme="")`

You can add your own themes using add_colorDF_theme() (see the example section on the help page).

5 Column styles

Styles of a colorDF object can be directly manipulated using df_style:

mtcars.c <- colorDF(mtcars)
df_style(mtcars.c, "sep") <- "; "

If interested, read the help file for df_style().

6 Utilities

colorDF comes with two utility functions. Firstly, it defines a summary method for colorful data frames which can also be used for any other data frame like object and which I find much more useful than the regular summary:

starwars %>% as.colorDF %>% summary
Color data frame 5 x 13:
  │Col       │Class    │NAs│unique
 1name      character  0    87
 2height    integer    6    46
 3mass      numeric   28    39
 4hair_colorcharacter  5    13
 5skin_colorcharacter  0    31
 6eye_color character  0    15
 7birth_yearnumeric   44    37
 8gender    character  3     5
 9homeworld character 10    49
10species   character  5    38
11films     list       0    24
12vehicles  list       0    11
13starships list       0    17

  │Summary                                                           
 1All values unique                                                 
 2 66 [167 <180> 191] 264                                           
 3  15 [  56 <  79>   84] 1358                                      
 4none: 37, brown: 18, black: 13, white: 4, blond: 3, auburn: 1, ...
 5fair: 17, light: 11, dark: 6, green: 6, grey: 6, pale: 5, ...     
 6brown: 21, blue: 19, yellow: 11, black: 10, orange: 8, red: 5, ...
 7  8 [ 35 < 52>  72] 896                                           
 8male: 62, female: 19, none: 2, hermaphrodite: 1                   
 9Naboo: 11, Tatooine: 10, Alderaan: 3, Coruscant: 3, ...           
10Human: 35, Droid: 5, Gungan: 3, Kaminoan: 2, ...                  
11Attack of th...: 13, The Phantom ...: 13, ...                     
12character(0): 76, Tribubble bongo: 2, ...                         
13character(0): 67, X-wing: 3, ...                                  

There is a directly visible (exported) version of the colorful summary called summaryColorDF:

starwars %>% summaryColorDF

The highlight() function allows to mark selected rows from the table:

foo <- starwars %>% select(name, species, homeworld) %>% 
  highlight(.$homeworld == "Tatooine")

(Unfortunately, the HTML representation of the ANSI terminal doesn’t show that one correctly).

7 Rmarkdown

The package is intended to be used in terminal. However, as you see above, it is possible to get the colored tables also in an rmarkdown document. For this, include the following chunk at the beginning of your document:

```{r echo=FALSE,include=FALSE}
options(crayon.enabled = TRUE)
knitr::knit_hooks$set(output = function(x, options){
  paste0(
    '<pre class="r-output"><code>',
    fansi::sgr_to_html(x = x, warn = FALSE),
    '</code></pre>'
  )
})
```

8 Issues

The main problem is that it relies on the crayon package, which unfortunately is sometimes wrong about whether the terminal has 255 colors or 16 (at least in the version on CRAN). Case in point, the colors do not render correctly in rstudio, despite the fact that the rstudio terminal is of course capable of showing all ANSI colors.