A visual CV for a chemist

This week at work I started using rbokeh, the R interface to Bokeh. The package allows to create web-based interactive plots. I was mostly excited about the zooming tools that a local R-Lady mentioned to me. They made data exploration so much easier, thanks a bunch Elena!

When checking out the doc, I saw an example called “Periodic table of the elements with additional info on hover”. While this was useless at work where I only made time series plots, I could set aside this application for my leisure time. I made an interactive CV for my husband, Damien, who is a chemist!

You’ll find the original periodic table example in rbokeh’s preview. My code is very similar to the one there!

Getting data

Elements

One gets the elements data from the package itself.

library("rbokeh")
library("dplyr")
data(elements)
knitr::kable(head(elements))
atomic.number symbol name atomic.mass CPK electronic.configuration electronegativity atomic.radius ion.radius van.der.Waals.radius IE.1 EA standard.state bonding.type melting.point boiling.point density metal year.discovered group period color type symx numbery massy namey
0 1 H Hydrogen 1.00794 #FFFFFF 1s1 2.20 37 120 1312 -73 gas diatomic 14 20 8.99e-05 nonmetal 1766 1 1 #baa2a6 nonmetal 1:0.1 1:0.8 1:0.15 1:0.3
1 2 He Helium 4.002602 #D9FFFF 1s2 NA 32 140 2372 0 gas atomic NA 4 0.00e+00 noble gas 1868 18 1 #bbbb88 noble gas 18:0.1 1:0.8 1:0.15 1:0.3
2 3 Li Lithium 6.941 #CC80FF [He] 2s1 0.98 134 76 (+1) 182 520 -60 solid metallic 454 1615 5.40e-01 alkali metal 1817 1 2 #a6cee3 alkali metal 1:0.1 2:0.8 2:0.15 2:0.3
3 4 Be Beryllium 9.012182 #C2FF00 [He] 2s2 1.57 90 45 (+2) NA 900 0 solid metallic 1560 2743 1.85e+00 alkaline earth metal 1798 2 2 #1f78b4 alkaline earth metal 2:0.1 2:0.8 2:0.15 2:0.3
4 5 B Boron 10.811 #FFB5B5 [He] 2s2 2p1 2.04 82 27 (+3) NA 801 -27 solid covalent network 2348 4273 2.46e+00 metalloid 1807 13 2 #33a02c metalloid 13:0.1 2:0.8 2:0.15 2:0.3
5 6 C Carbon 12.0107 #909090 [He] 2s2 2p2 2.55 77 16 (+4) 170 1087 -154 solid covalent network 3823 4300 2.26e+00 nonmetal Ancient 14 2 #baa2a6 nonmetal 14:0.1 2:0.8 2:0.15 2:0.3

It looks fine but some elements recently got new names. I wouldn’t know about it from my own readings, but well my husband did, and he can recommend a radio show in French about it because one of his favourite tweeps is the interviewee. He obviously thinks I can drive traffic to any website I want with this blog. I couldn’t find how to update the table of the package so opened an issue at rbokeh and will selfishly solve the issue for myself here.

The ones that got new names compared to the table of the package are 113, 114, 115, 116, 117, and 118. Actually 118 wasn’t even in the rbokeh table so we’ll add it. I’m adding the atomic masses too but I was told that an atomic mass superior to 82 doesn’t have much interest anyway because of the unstability of the elements.

elements <- filter(elements, !atomic.number %in% c(113, 114, 115, 116, 117))

renamed_elements <- data.frame(atomic.number = c(113, 114, 115, 116, 117, 118),
                                   symbol = c("Nh", "Fl", "Mc", "Lv", "Ts", "Og"),
                                   name = c("Nihonium", "Flerovium", "Moscovium", "Livermorium", "Tennessine", "Oganesson"),
                                   atomic.mass = c("[284]", "[289]", "[288]", "[293]", "[294]", "[294]"),
                               group = c("13", "14", "15", "16", "17", "18"),
                               period = rep("7", 6))

elements <- bind_rows(elements, renamed_elements)

knitr::kable(tail(elements))
atomic.number symbol name atomic.mass CPK electronic.configuration electronegativity atomic.radius ion.radius van.der.Waals.radius IE.1 EA standard.state bonding.type melting.point boiling.point density metal year.discovered group period color type symx numbery massy namey
85 113 Nh Nihonium [284] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 13 7 NA NA NA NA NA NA
86 114 Fl Flerovium [289] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 14 7 NA NA NA NA NA NA
87 115 Mc Moscovium [288] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 15 7 NA NA NA NA NA NA
88 116 Lv Livermorium [293] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 16 7 NA NA NA NA NA NA
89 117 Ts Tennessine [294] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 17 7 NA NA NA NA NA NA
90 118 Og Oganesson [294] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 18 7 NA NA NA NA NA NA

Okay now the table looks like a 2017 table of elements.

Experience

I didn’t want to have additional information about the elements but rather pieces of experience of my husband who was actually thrilled to fill a table with stuff he’s done with elements. Here is what he sent me.

damien <- readr::read_csv2("data/2017-02-03-chemist_Elements.csv")
## Parsed with column specification:
## cols(
##   Element = col_character(),
##   `Why did I use it?` = col_character(),
##   Place = col_character()
## )
knitr::kable(head(damien))
Element Why did I use it? Place
H I am currently working on the hydrogenation of alkenes. And, well, H is everywhere! Hangzhou, Paris, Berlin, Tarragona
He It is not possible to cool large superconducting coils without liquid He. Berlin
Li Butyl lithium is a very powerful base! Hangzhou
C I am currently working on the vibrations between carbon monoxide and metallic surfaces. And, well, C is everywhere! Hangzhou, Paris, Berlin, Tarragona
N Infrared spectrometer works much better in liquid nitrogen Paris, Berlin, Tarragona
O I am currently working on the vibrations between carbon monoxide and metallic surfaces. And, well, O is everywhere! Hangzhou, Paris, Berlin, Tarragona

I think it’s funny to print Damien’s head. I was less amused by the second column name because of the spaces, so I renamed it before joining it to the original elements table. I also replaced the missing values of the elements table, corresponding to elements my husband had nothing to say about, with empty strings.

names(damien)[2] <- "desc"
elements <- left_join(elements, damien, by = c("symbol" = "Element"))
elements <- mutate(elements, Place = ifelse(is.na(Place), "", Place))
elements <- mutate(elements, desc = ifelse(is.na(desc), "", desc))

Drawing the table

Preparing the colours and coordinates

Nothing new here, I’m pretty much doing the same as in the doc, dplyr style.

places <- unique(elements$Place)
colors <- c("#a6cee3", "#1f78b4", "#fdbf6f", "white", "#b2df8a", "#33a02c",
            "#bbbb88", "#baa2a6", "#e08e79")
colors <- data.frame(Place = places, color = colors)
elements <- select(elements, - color)
elements <- left_join(elements, colors, by = "Place")

This is the part where the tutorial indicates how to create coordinates for putting every text in its place.

elements <- mutate(elements, symx = paste0(group, ":0.1"))
elements <- mutate(elements, numbery = paste(period, ":0.8", sep = ""))
elements <- mutate(elements, massy = paste(period, ":0.15", sep = ""))
elements <- mutate(elements, namey = paste(period, ":0.3", sep = ""))

Plotting itself

I haven’t got a ton of experience with rbokeh, the main syntax differences I noted compared to ggplot2 was the piping and the fact that you need to specify data for each layer. You’ll find a better comparison on Bob Rudis’ blog.

But in the case of the period table I only really needed to copy paste code, thanks a lot to Ryan Hafen for his awesome package and for the cool example. The part of the code I changed is hover = list(name, desc, place) which is the part where I choose to show the experience my husband associates with each element. In the original example the hover tool showed more info about elements. Note that Damien doesn’t even associates something really interesting with gold like, you know, a wedding ring. Bummer.

# See you create a table like this and add a serious title
p <- figure(title = "Periodic Table of Damien Cornu's experience", tools = c("resize", "hover"),
            ylim = as.character(c(7:1)), xlim = as.character(1:18),
            xgrid = FALSE, ygrid = FALSE, xlab = "", ylab = "",
            height = 445, width = 800) %>%
  
  # Here the rectangles are created, 
  # without experience rectangles get a while fill
  ly_crect(group, period, data = elements, 0.9, 0.9,
           fill_color = color,
           line_color = "grey", fill_alpha = 0.6,
           hover = list(name, desc, Place)) %>%
  
  # add symbol text
  ly_text(symx, period, text = symbol, data = elements,
          font_style = "bold", font_size = "10pt",
          align = "left", baseline = "middle") %>%
  
  # add atomic number text
  ly_text(symx, numbery, text = atomic.number, data = elements,
          font_size = "6pt", align = "left", baseline = "middle") %>%
  
  # add name text
  ly_text(symx, namey, text = name, data = elements,
          font_size = "4pt", align = "left", baseline = "middle") %>%
  
  # add atomic mass text
  ly_text(symx, massy, text = atomic.mass, data = elements,
          font_size = "4pt", align = "left", baseline = "middle")

Displaying the CV

Maybe the way I display the rbokeh plot on this page is a dirty hack. Using the htmlwidget package I saved the widget,

htmlwidgets::saveWidget(p, file = "damien.html")

And then I simply included the html file thus created. If you knit a html, not a html via a .md as is the case with a Jekyll website, you don’t need these two steps to display a widget. At work I made a flexdashboard with rbokeh and it couldn’t have been easier.

htmltools::includeHTML("https://raw.githubusercontent.com/masalmon/masalmon.github.io/master/_source/damien.html")