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")
Note: this period table of elements doesn’t show the lanthanides and actinides.
Now you can browse the periodic table of my husband’s experience, which he’ll soon include on his website as a visual CV. It includes his research but also the fact that he was a guide for tours about Marie Curie’s life. I’m happy for him not to use radioactive elements for real, and of course for him to support women in science (I’ll get him this pretty sticker if Alice ends up printing it).
Now it’s your turn to create an interactive periodic table for the chemist in your life! I’d also be curious of how to map one’s experience in other fields than chemistry. I made a leaflet
map for Damien and my websites with places where we studied or worked (you now know he really didn’t marry me for my good looks) which is a pretty straightforward “experience-mapping” method but maybe one could imagine a phylogenetic tree for a biologist? You tell me!