Colorful tables in a terminal

It all started when I wanted to have significant p-values shown on the terminal colored in red. The R terminal is capable of showing colors, simple formatting (like italics or bold) and Unicode characters, thanks to the actual terminal that does the job of displaying R output – whether it is the console of rstudio or a terminal window. You can see that when you use tibbles from tidyverse: they use some very limited formatting (like showing “NA” in red).

I ended up writing a new package, colorDF. The package defines a new class of data frames, but it really does not change their behavior – just the way they are shown (specifically, it modifies some attributes and introduces a print.colorDF function for printing). If you change a tibble to a colorDF, it will still behave exactly like a tibble, but it will be shown in color:

# Color data frame 6 x 87: # (Showing rows 1 - 20 out of 87) │name │height│mass │birth_year│gender │probability 1 Luke Skywalker 172 77 19male 0.0083 2 C-3PO 167 75 112NA 0.0680 3 R2-D2 96 32 33NA 0.0596 4 Darth Vader 202 136 42male 0.0182 5 Leia Organa 150 49 19female 0.0138 6 Owen Lars 178 120 52male 0.0115 7 Beru Whitesun lars 165 75 47female 0.0489 8 R5-D4 97 32 NANA 0.0040 9 Biggs Darklighter 183 84 24male 0.0954 10 Obi-Wan Kenobi 182 77 57male 0.0242 11 Anakin Skywalker 188 84 42male 0.0066 12 Wilhuff Tarkin 180 NA 64male 0.0605 13 Chewbacca 228 112 200male 0.0587 14 Han Solo 180 80 29male 0.0519 15 Greedo 173 74 44male 0.0204 16Jabba Desilijic Tiure 175 1358 600hermaphrodite0.0929 17 Wedge Antilles 170 77 21male 0.0457 18 Jek Tono Porkins 180 110 NAmale 0.0331 19 Yoda 66 17 896male 0.0931 20 Palpatine 170 75 82male 0.0012

Yes, it looks like that in the terminal window!

You can read all about it in the package vignette (please use the package from github, the CRAN version is lagging behind). Apart from the print function, I implemented also a summary function which is more informative than the default summary function for the data frames.

starwars %>% as.colorDF %>% summary
# Color data frame 5 x 13: │Col │Class│NAs │unique│Summary 1name <chr> 0 87All values unique 2height <int> 6 45 66 [167 <180> 191] 264 3mass <dbl> 28 38 15.0 [ 55.6 < 79.0> 84.5] 1358.0 4hair_color<chr> 5 12none: 37, brown: 18, black: 13, white: 4, blond: 3, auburn: 1, … 5skin_color<chr> 0 31fair: 17, light: 11, dark: 6, green: 6, grey: 6, pale: 5, brown… 6eye_color <chr> 0 15brown: 21, blue: 19, yellow: 11, black: 10, orange: 8, red: 5, … 7birth_year<dbl> 44 36 8 [ 35 < 52> 72] 896 8gender <chr> 3 4male: 62, female: 19, none: 2, hermaphrodite: 1 9homeworld <chr> 10 48Naboo: 11, Tatooine: 10, Alderaan: 3, Coruscant: 3, Kamino: 3, … 10species <chr> 5 37Human: 35, Droid: 5, Gungan: 3, Kaminoan: 2, Mirialan: 2, Twi'l… 11films <lst> 0 24Attack of the Clones: 40, Revenge of the Sith: 34, The Phantom … 12vehicles <lst> 0 11Imperial Speeder Bike: 2, Snowspeeder: 2, Tribubble bongo: 2, A… 13starships <lst> 0 17Millennium Falcon: 4, X-wing: 4, Imperial shuttle: 3, Naboo fig…

For numeric vectors, by default the function shows the minimum, quartiles and median, but it can also produce a boxplot-like graphical summary. Since the function works also on lists, implementing a text terminal based boxplot function was super easy:

term_boxplot(Sepal.Length ~ Species, data=iris, width=90)
# Color data frame 5 x 4: │Col │Class│NAs │unique│Summary 1setosa <dbl> 0 15╾──────┤ + ├────────╼ 2versicolor<dbl> 0 21 ╾─────────┤ + ├──────────╼ 3virginica <dbl> 0 21 ╾──────────────────┤ + ├──────────────╼ 4Range <chr> 0 1Only one value: Range: 4.3 - 7.9

Cool, isn’t it?

tagcloud: creating tag / word clouds

May I present my new package: tagcloud. Tag clouds is for creating, um, tag clouds (aka word clouds). It is based on the code from the wordcloud package, but (i) has no tools for analysing word frequencies, instead (ii) focuses on doing better tag clouds. As to (ii), it adapts to the geometry of the window better and can produce different layouts. Also, with the extrafont package, it can use just any fonts you can think of:

sample8

The general syntax is simple. The function tagcloud takes one mandatory argument, the tags to display — a character vector. In the example below, I use the font names available through the extrafont package¹, but it can be anything.

library( extrafont )
tags <- sample( fonts(), 50 )
tagcloud( tags )
dev.copy2pdf( file= "sample1.pdf", out.type= "cairo" )

Note the use of cairo in the above, otherwise the PDF does not include the fonts and the result is not impressive. Here is the result:

sample1

OK, let’s add some weights and colors. Also, wouldn’t it be cool if each font name was displayed in the actual font?

weights <- rgamma( 50, 1 )
colors <- colorRampPalette( brewer.pal( 12, "Paired" ) )( 50 )
tagcloud( tags, weights= weights, col= colors, family= tags )

sample2

How about mixed vertical and horizontal tags?

tagcloud( tags, weights= weights, col= colors, family= tags, 
fvert= 0.5 )

sample3

The fvert parameter specifies the proportion of tags that should be displayed vertically rather than horizontally.

Or a different layout?

tagcloud( tags, weights= weights, col= colors, 
family= tags, algorithm= "fill" )

sample4

Tagclouds comes with additional tools. Firstly, you have editor.tagcloud — a very minimalistic interactive editor. You need to store the object invisibly returned from tagcloud:

tc <- tagcloud( tags, weights= weights, col= colors, family= tags )
tc2 <- editor.tagcloud( tc )
plot( tc2 )

With strmultline you can break up long, multi-word tags into multi-line tags:

tagcloud( strmultline( tags ), weights= weights, col= colors, family= tags )

The result is as follows (notice “Andale Mono” or “DejaVu Sans Light”):

sample5

Finally, smoothPalette makes it easy to generate a gradient from numbers. Imagine that we want to code some other numeric information (this could be a p-value, for example) with a smooth gradient from light grey (low value) to black (high value):

newvar <- runif( 50 )
colors2 <- smoothPalette( newvar )
tagcloud( tags, weights=weights, col=colors2, family= tags )

By default, smoothPalette uses a grey-white gradient, but it can actually use any kind of color palette.

sample6


1: In order to use the fonts installed on your system, you need to import them — preferably as root — using the extrafont package. At least in my Ubuntu installation you should provide the paths to where your TTF fonts are installed, for example:

library( extrafont )
font_import( paths= "/usr/share/fonts/truetype/" )