3D Interactive Charts
Using the plotly package
1 Setting up R Packages
Plot Fonts and Theme
Show the Code
library(systemfonts)
library(showtext)
library(ggrepel)
library(marquee)
## Clean the slate
systemfonts::clear_local_fonts()
systemfonts::clear_registry()
##
showtext_opts(dpi = 96) # set DPI for showtext
sysfonts::font_add(
family = "Alegreya",
regular = "../../../../../../fonts/Alegreya-Regular.ttf",
bold = "../../../../../../fonts/Alegreya-Bold.ttf",
italic = "../../../../../../fonts/Alegreya-Italic.ttf",
bolditalic = "../../../../../../fonts/Alegreya-BoldItalic.ttf"
)
sysfonts::font_add(
family = "Roboto Condensed",
regular = "../../../../../../fonts/RobotoCondensed-Regular.ttf",
bold = "../../../../../../fonts/RobotoCondensed-Bold.ttf",
italic = "../../../../../../fonts/RobotoCondensed-Italic.ttf",
bolditalic = "../../../../../../fonts/RobotoCondensed-BoldItalic.ttf"
)
showtext_auto(enable = TRUE) # enable showtext
##
theme_custom <- function() {
theme_bw(base_size = 10) +
theme_sub_axis(
title = element_text(
family = "Roboto Condensed",
size = 8
),
text = element_text(
family = "Roboto Condensed",
size = 6
)
) +
theme_sub_legend(
text = element_text(
family = "Roboto Condensed",
size = 6
),
title = element_text(
family = "Alegreya",
size = 8
)
) +
theme_sub_plot(
title = element_text(
family = "Alegreya",
size = 14, face = "bold"
),
title.position = "plot",
subtitle = element_text(
family = "Alegreya",
size = 10
),
caption = element_text(
family = "Alegreya",
size = 6
),
caption.position = "plot"
)
}
## Use available fonts in ggplot text geoms too!
ggplot2::update_geom_defaults(geom = "text", new = list(
family = "Roboto Condensed",
face = "plain",
size = 3.5,
color = "#2b2b2b"
))
ggplot2::update_geom_defaults(geom = "label", new = list(
family = "Roboto Condensed",
face = "plain",
size = 3.5,
color = "#2b2b2b"
))
ggplot2::update_geom_defaults(geom = "marquee", new = list(
family = "Roboto Condensed",
face = "plain",
size = 3.5,
color = "#2b2b2b"
))
ggplot2::update_geom_defaults(geom = "text_repel", new = list(
family = "Roboto Condensed",
face = "plain",
size = 3.5,
color = "#2b2b2b"
))
ggplot2::update_geom_defaults(geom = "label_repel", new = list(
family = "Roboto Condensed",
face = "plain",
size = 3.5,
color = "#2b2b2b"
))
## Set the theme
ggplot2::theme_set(new = theme_custom())
## tinytable options
options("tinytable_tt_digits" = 2)
options("tinytable_format_num_fmt" = "significant_cell")
options(tinytable_html_mathjax = TRUE)
## Set defaults for flextable
flextable::set_flextable_defaults(font.family = "Roboto Condensed")
2 Introduction
The plotly package in R, created by Carson Sievert allows the plotly.js JavaScript library to be used in R, using R syntax. It offers a wide variety of 2D and 3D interactive charts.
We will today see how to make our charts interactive, with popups and labels. And we can zoom in and out too.
3D charts are generally not a good idea, the literature says. but sometimes, they are exactly the thing that is needed, especially in teaching and learning. So we will look at those too. Both of these aspects using a new package called plotly.
For form’s sake, we will proceed as we have always done, looking at a dataset (however familiar), writing up its Data Dictionary, and then making plots.
3 Examine the Data
We will use the penguins dataset built into R itself. Your should try other datasets too!
Here is a glimpse of the data:
Rows: 344
Columns: 8
$ species <fct> Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Ad…
$ island <fct> Torgersen, Torgersen, Torgersen, Torgersen, Torgersen, Tor…
$ bill_len <dbl> 39.1, 39.5, 40.3, NA, 36.7, 39.3, 38.9, 39.2, 34.1, 42.0, …
$ bill_dep <dbl> 18.7, 17.4, 18.0, NA, 19.3, 20.6, 17.8, 19.6, 18.1, 20.2, …
$ flipper_len <int> 181, 186, 195, NA, 193, 190, 181, 195, 193, 190, 186, 180,…
$ body_mass <int> 3750, 3800, 3250, NA, 3450, 3650, 3625, 4675, 3475, 4250, …
$ sex <fct> male, female, female, NA, female, male, female, male, NA, …
$ year <int> 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007…
3.1 Data Dictionary
-
bill_len- length of the penguin’s bill in millimeters (continuous) -
bill_dep- depth of the penguin’s bill in millimeters (continuous) -
flipper_len- length of the penguin’s flipper in millimeters (continuous) -
body_mass- mass of the penguin in grams (continuous) -
year- year of observation (discrete, integer)
-
species- the species of penguin (categorical) -
island- the island where the penguin was observed (categorical)
4 Our first interactive chart with {plotly}
plotly uses the tidyverse syntax and supports use of the pipe as well ( both the tidyverse pipe and the R-native pipe). So let’s do this:
Note the automatic toolbar at the top-left of the chart; this allows all sorts of interactivity. Each point in the chart pops up a set of values for the two variables, and the popup itself is coloured based on the grouping variable.
All these aspects we will customize presently, once we have understood the basics of the plotly API.
5 The {plotly} API defined
If we type help(plot_ly) in our Console, we obtain the following parameters for the plot_ly() command:
data: The Data frame driving the charttype: chart type (e.g. “scatter”, “bar”, “box”…)name: trace name. Acts like grouping variablecolor: Colour for marker ( i.e. symbol glyph), fill, text…colors: Colour palettealpha: Colour saturation,stroke: Stroke colour when Markers have separate colour and fill attributesstrokes: Strokes palettealpha_stroke: Stroke colour saturationsize: Controls mapping of data to size/width of marker/text/…sizes: c(10, 100): Scale for mappingsizeto variablespan: Controls mapping of data tostroke-sizespans: c(1, 20): Scale for mappingspanto variablesymbol: Discrete values for type of symbol usedsymbols: Controls mapping ofsymbolto variable (thinkpch)linetype: “solid”, “dot”, “dash”, “longdash”, “dashdot”, or “longdashdot”linetypes: Controls mapping oflinetypeto variablesplit: Grouping variableframe: Variable values for chart animation ( yes!)width: width in pixelsheight: height in pixelssource: Used withshinyapps. ( Yet another R course!!) )
This function is rather like ggplot() that initiates a plot and passes on global chart variables to the subsequent layers of the chart. However, with type specified, it is capable of building a chart on its own, unlike with ggplot2.
In order to learn the different chart types, we will not specify type in theplot_ly()` command, and use specific chart oriented commands to achieve our purposes. This will become clear in the following.
6 Basic 2D Chart Types in {plotly}
Let us rapidly look at plotly code to generate a set of basic familiar charts.
6.1 Scatter Revisited
Show the Code
penguins <- penguins %>% drop_na()
model <- stats::lm(body_mass ~ flipper_len,
data = penguins
)
penguins %>%
mutate(island = as_factor(island), species = as_factor(species)) %>%
plot_ly() %>%
add_trace(
x = ~flipper_len, y = ~body_mass,
name = ~species,
symbol = ~species,
size = ~ as.integer(species), # Note!!
sizes = c(5, 25),
type = "scatter", mode = "markers"
) %>%
add_lines(
x = ~flipper_len,
y = ~ stats::fitted(model),
name = "Linear Regression Line", showlegend = T
) %>%
## See <https://plotly.com/r/reference/layout/>
layout(
font = list(family = "Roboto Condensed"),
title = list(
text = "Penguins, with Linear Model",
subtitle = list(text = "Scatter with Colour with Size")
),
legend = list(title = list(text = "Species")),
margin = c(5, 20, 5, 20),
plot_bgcolor = "#DCE2F0",
paper_bgcolor = "#7b9acc",
modebar = list(bgcolor = "white", activecolor = "black"),
xaxis = list(title = "Flipper Length", gridcolor = "white"),
yaxis = list(title = "Body Mass in grams", gridcolor = "white")
)6.2 Line
Show the Code
apple <- read_csv("https://raw.githubusercontent.com/plotly/datasets/master/2014_apple_stock.csv")
appleShow the Code
apple %>%
mutate(AAPL_x = as.Date(AAPL_x)) %>%
plot_ly(
x = ~AAPL_x,
y = ~AAPL_y, type = "scatter",
mode = "lines",
name = "Share Prices (in USD)"
) %>%
layout(
title = "Apple Share Prices over time (2014)",
plot_bgcolor = "#e5ecf6",
xaxis = list(
title = "Time",
zerolinecolor = "#ffff",
zerolinewidth = 2,
gridcolor = "ffff"
),
yaxis = list(
title = "Apple Stock Price",
zerolinecolor = "#ffff",
zerolinewidth = 2,
gridcolor = "ffff"
),
showlegend = TRUE,
margin = c(5, 5, 5, 5)
)6.3 Bars and Histograms
Show the Code
Show the Code
# number of diamonds by cut and clarity (n)
cc <- count(diamonds, cut, clarity)
ccShow the Code
Show the Code
6.4 Histogram and Density
plot_ly(diamonds, x = ~cut, color = ~clarity) %>%
add_histogram() %>%
layout(
title = "Diamond Prices",
autosize = TRUE,
margin = list(l = 50, r = 20, b = 20, t = 40, pad = 20)
)6.5 Box Plots
p <- plot_ly(diamonds,
y = ~price, color = I("black"),
alpha = 0.1, boxpoints = "suspectedoutliers"
)
p1 <- p %>% add_boxplot(x = "Overall")
p2 <- p %>% add_boxplot(x = ~cut, color = ~cut, fillcolor = ~cut)
subplot(
p1, p2,
shareY = TRUE,
widths = c(0.2, 0.8), margin = 0.05
) %>% hide_legend()6.6 Combo Chart
6.7 Maps
7 Basic of 3D charts in {plotly}
7.1 3D Scatter
7.2 3D Surface
Show the Code
x0 <- 1
y0 <- -0.5
sigma <- 1
x <- seq(-3, 3, length.out = 80)
y <- seq(-3, 3, length.out = 80)
grid <- expand.grid(x = x, y = y)
grid$z <- exp(-(((grid$x - x0)^2 + (grid$y - y0)^2) / (2 * sigma^2)))
z_matrix <- matrix(grid$z, nrow = length(x), ncol = length(y))
plot_ly(
x = ~x,
y = ~y,
z = ~z_matrix,
type = "surface",
colorscale = "Viridis"
) %>%
layout(
title = list(
text = "3D Gaussian RBF Surface<br><span style='font-size: 14px;'>Centered at the [1,-0.5]</span>"
),
scene = list(
xaxis = list(title = "x"),
yaxis = list(title = "y"),
zaxis = list(title = "phi(r)")
),
autosize = TRUE,
margin = list(l = 20, r = 20, b = 40, t = 40, pad = 40)
)7.3 3D Combo Chart
And what exactly do you intend here, Arvind?
8 Customizing the {plotly} chart
8.1 Themes
8.2 Facets
8.3 Toolbar
8.4 Custom Popups
8.5 Animations
9 Conclusion
10 References
- Plotly R Open Source Graphing Library https://plotly.com/r/
- Carson Sievert. Interactive web-based data visualization with R, plotly, and shiny. https://plotly-r.com/
- Plotly Figure Reference. https://plotly.com/r/reference/index/
R Package Citations
| Package | Version | Citation |
|---|---|---|
| plotly | 4.12.0 | Sievert (2020) |
