Week 5: Interactive Graphics

Robert W. Walker

Overview

  1. AMA
  2. Some Addenda on Tables
  3. Interactive Graphics in R
    • Network data and interaction with networkD3.
    • Plotly and ggplotly
    • Crosstalk related tools
    • ggiraph

The Assignment for this week

Produce two interactive graphics for the portfolio.

AMA

If there are things you want to figure out with quarto, what are they?

  • One of your classmates investigated comments. Comments have a nasty interaction with embed-resources in quarto because the pages become sort of dynamic.

A Flag Change and a Difference Between Quarto and RMarkdown

embed-resources

Worth noting the self-contained it currently supports is deprecated.

On Tables

A question that a classmate posted

datatable is amazing

My post for this week.

Code
library(tidyverse)
library(magrittr)
library(DT)
library(gt)
library(gtExtras)
# install with remotes::install_github('jimjam-slam/ggflags')
library(countrycode)
library(ggflags)
load(url("https://github.com/robertwwalker/robertwwalker.github.io/raw/main/posts/HumanRightsTable/data/HumanRightsProtectionScores_v4.01.RData"))
HR.Data <- x
rm(x)
HR.Data <- HR.Data %>%
    left_join(., codelist, by = c(COW = "cown"))
library(countrycode)
Flags <- read.csv(url("https://github.com/robertwwalker/robertwwalker.github.io/raw/main/posts/HumanRightsTable/data/flags_iso.csv"))
HR.Summary <- HR.Data %>%
    group_by(country.name.en) %>%
    mutate(Obs = n()) %>%
    filter(Obs == 74) %>%
    arrange(YEAR) %>%
    summarise(Obs = mean(Obs), Mean = mean(theta_mean, na.rm = TRUE), SD = sd(theta_mean),
        hr_data = list(theta_mean), .groups = "drop")
CCs <- codelist %>%
    select(country.name.en, iso3c)
HR.Summary <- HR.Summary %>%
    left_join(., CCs) %>%
    left_join(., Flags, by = c(iso3c = "Alpha.3.code")) %>%
    select(-iso3c, -Country, -Alpha.2.code) %>%
    relocate(., URL, .after = country.name.en)
My.Table.1 <- HR.Summary %>%
    filter(substr(country.name.en, 1, 1) %in% LETTERS[1:9]) %>%
    gt() %>%
    # format the numeric output to 3 digit rounding
fmt_number(columns = c(Mean, SD), decimals = 3) %>%
    # create nice labels for a few ugly variable names
cols_label(country.name.en = "Country", SD = "Std. Dev.", hr_data = "Time Series Plot",
    URL = "Flag") %>%
    # Plot the sparklines from the list column
gt_plt_sparkline(hr_data, type = "ref_median", same_limit = TRUE) %>%
    # Plot the flags from the included URL's in the data
gt_img_rows(URL, img_source = "web", height = 30) %>%
    # use the guardian's table theme
gt_theme_guardian() %>%
    # give hulk coloring to the Mean Human Rights Score
gt_hulk_col_numeric(Mean) %>%
    # create a header and subheader
tab_header(title = "Human Rights Data Summary", subtitle = "Data from Fariss (2020): 1st Half") %>%
    # create the spanner heading
tab_spanner(label = "Human Rights Measures", columns = c(Mean, SD, hr_data))
My.Table.1
Human Rights Data Summary
Data from Fariss (2020): 1st Half
Country Flag Obs Human Rights Measures
Mean Std. Dev. Time Series Plot
Afghanistan 74 −0.808 1.584 -2
Albania 74 −0.734 1.132 1
Argentina 74 −0.110 0.866 1.26
Australia 74 1.496 0.482 1.9
Austria 74 1.363 0.716 2.2
Belgium 74 1.950 0.870 3.2
Bhutan 74 1.640 0.895 2.4
Bolivia 74 0.031 0.600 0.47
Brazil 74 −0.987 0.438 -1
Bulgaria 74 −0.141 0.816 1.29
Canada 74 1.514 1.087 3.2
Chile 74 −0.116 1.098 0.53
China 74 −1.690 0.587 -1
Colombia 74 −1.549 0.337 0
Costa Rica 74 1.407 0.589 2.2
Cuba 74 −0.780 0.677 0
Czechia 74 0.234 1.800 3
Denmark 74 2.409 0.799 3.4
Dominican Republic 74 −0.353 0.478 -0.22
Ecuador 74 −0.066 0.409 0.90
Egypt 74 −0.954 0.339 -1
El Salvador 74 −0.457 1.026 0.27
Ethiopia 74 −1.251 0.934 -2
Finland 74 2.234 0.985 2.5
France 74 0.733 0.761 1.7
Greece 74 0.344 0.677 1.3
Guatemala 74 −1.243 1.057 0
Haiti 74 −0.701 0.783 1
Honduras 74 −0.005 0.601 -0.37
Hungary 74 0.317 1.178 1.45
Iceland 74 4.449 0.772 5.2
Iran 74 −1.490 0.593 -2
Iraq 74 −1.759 0.644 -2
Ireland 74 1.715 0.830 3.1
Italy 74 0.748 0.578 1.9
Code
My.Table.2 <- HR.Summary %>%
    filter(substr(country.name.en, 1, 1) %in% LETTERS[10:26]) %>%
    gt() %>%
    # format the numeric output to 3 digit rounding
fmt_number(columns = c(Mean, SD), decimals = 3) %>%
    # create nice labels for a few ugly variable names
cols_label(country.name.en = "Country", SD = "Std. Dev.", hr_data = "Time Series Plot",
    URL = "Flag") %>%
    # Plot the sparklines from the list column
gt_plt_sparkline(hr_data, type = "ref_median", same_limit = TRUE) %>%
    # Plot the flags from the included URL's in the data
gt_img_rows(URL, img_source = "web", height = 30) %>%
    # use the guardian's table theme
gt_theme_guardian() %>%
    # give hulk coloring to the Mean Human Rights Score
gt_hulk_col_numeric(Mean) %>%
    # create a header and subheader
tab_header(title = "Human Rights Data Summary", subtitle = "Data from Fariss (2020): 2nd Half") %>%
    # create the spanner heading
tab_spanner(label = "Human Rights Measures", columns = c(Mean, SD, hr_data))
My.Table.2
Human Rights Data Summary
Data from Fariss (2020): 2nd Half
Country Flag Obs Human Rights Measures
Mean Std. Dev. Time Series Plot
Japan 74 1.347 0.841 2.9
Jordan 74 −0.167 0.332 0.55
Lebanon 74 −0.501 0.510 0.04
Liberia 74 0.016 0.996 0.8
Luxembourg 74 4.610 0.751 5.3
Mexico 74 −0.698 0.442 -1
Mongolia 74 1.980 0.897 1.0
Nepal 74 −0.407 0.731 0.50
Netherlands 74 2.179 1.623 3.8
New Zealand 74 3.388 0.506 3.7
Nicaragua 74 −0.335 0.810 -0.85
Norway 74 2.580 1.241 4.3
Oman 74 1.083 0.488 1.1
Panama 74 0.535 0.924 2.66
Paraguay 74 −0.432 0.868 1.08
Peru 74 −0.398 0.847 1.07
Philippines 74 −1.443 0.562 -2
Poland 74 0.229 1.256 1.83
Portugal 74 0.513 1.449 2.1
Romania 74 −0.552 0.988 1
Russia 74 −1.596 0.393 -1
Saudi Arabia 74 −0.087 0.474 -1.12
South Africa 74 −1.014 0.589 -1
Spain 74 0.390 0.706 1.27
Sweden 74 1.675 1.090 3.2
Switzerland 74 1.178 0.833 2.6
Syria 74 −1.051 0.685 -2
Thailand 74 −0.512 0.408 -0.77
Turkey 74 −0.890 0.496 -2
United Kingdom 74 0.891 0.895 2.7
United States 74 0.232 1.233 -0.17
Uruguay 74 0.649 1.412 3.18
Venezuela 74 −0.586 0.703 -1.71

Other Table Questions?

Interactive Graphics

  1. networkD3
  2. plotly and ggplotly
  3. crosstalk tools
  4. ggiraph

networkD3

The Data

Code
library(jsonlite)
URL <- paste0("https://cdn.rawgit.com/christophergandrud/networkD3/", "master/JSONdata/energy.json")
Energy <- fromJSON(URL)
Links <- Energy$links
pivot_wider(Links, id_cols = source, names_from = target, values_from = value) %>%
    knitr::kable()
source 1 2 3 4 5 9 12 13 14 16 17 18 19 20 21 22 24 26 15 28 30 31 32 33 37 42 41 11
0 124.73 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
1 NA 0.597 26.86 280.3 81.1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
6 NA 35.000 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
7 NA NA NA 35.0 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
8 NA NA NA NA NA 11.6 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
10 NA NA NA NA NA 64.0 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
9 NA NA NA 75.6 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
11 NA NA NA NA NA NA 10.6 22.505 46.2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
15 NA NA 56.69 NA NA NA 342.2 40.858 113.7 104 27.1 37.8 4.412 7.86 90 93.5 NA NA NA NA NA NA NA NA NA NA NA NA
23 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 40.7 NA NA NA NA NA NA NA NA NA NA NA
25 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 82.2 NA NA NA NA NA NA NA NA NA NA NA
5 NA NA 1.40 NA NA NA 48.6 0.129 NA NA NA NA 2.096 NA NA NA NA 152 NA NA NA NA NA NA NA NA NA NA
27 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 7.01 NA NA NA NA NA NA NA NA NA
17 NA NA 6.24 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 20.9 NA NA NA NA NA NA NA NA
28 NA NA NA NA NA NA NA NA NA NA NA 20.9 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
29 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 7.00 NA NA NA NA NA NA NA NA NA
2 NA NA NA NA NA NA 121.1 NA NA NA NA 135.8 3.640 4.41 NA NA NA NA NA NA 129 14.5 206 33.2 NA NA NA NA
34 4.38 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
24 NA NA NA NA 123.0 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
35 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 840 NA NA NA NA NA NA NA NA NA NA
36 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 504 NA NA NA
38 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 108 NA NA NA
37 NA 611.990 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
39 77.81 NA NA 56.6 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
40 NA NA NA NA NA NA NA 70.672 193.0 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
41 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 59.90 NA NA NA NA NA NA NA NA NA
42 NA NA NA NA NA NA NA NA 19.3 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
43 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 19.3 59.9 NA
4 NA NA NA NA NA NA 46.5 NA NA NA NA NA 0.882 NA NA NA NA 400 NA NA NA NA NA NA NA NA NA NA
26 NA NA 787.13 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 525.53 NA NA NA NA NA NA NA NA 79.3
44 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 9.45 NA NA NA NA NA NA NA NA NA
45 182.01 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
46 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 19.01 NA NA NA NA NA NA NA NA NA
47 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 289.37 NA NA NA NA NA NA NA NA NA

The Plot

Code
library(networkD3)
# Plot
sankeyNetwork(Links = Energy$links, Nodes = Energy$nodes, Source = "source",
    Target = "target", Value = "value", NodeID = "name", units = "TWh", fontSize = 12,
    nodeWidth = 30)

Static picture

The Link

plotly and ggplotly

First, let me use ggplotly on a ggplot. This will sort of function as a completion of the assignment from last week. That said, I think it would be better if I spliced the data randomly to keep them off the lower triangle. It is doable; I didn’t think of it until I had done it.

The Data

Description

Code
library(DT)
age_gaps <- readr::read_csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2023/2023-02-14/age_gaps.csv")
datatable(age_gaps)

The ggplot

Code
AgeGapsGG <- ggplot(age_gaps) + aes(x = actor_1_age, y = actor_2_age, size = age_difference,
    color = age_difference, text = paste0(release_year, ": ", movie_name, "\n Director: ",
        director, " \n", actor_1_name, ", Age:", actor_1_age, "\n", actor_2_name,
        ", Age: ", actor_2_age)) + geom_point(alpha = 0.1) + guides(size = "none") +
    labs(title = "Actor Age Differentials", color = "Age Difference", x = "Age of Actor 1",
        y = "Age of Actor 2", caption = "Data from #tidyTuesday")
AgeGapsGG

ggplotly

Code
library(plotly)
ggplotly(AgeGapsGG, tooltip = c("text", "color"))

The plotly package

plotly as a package has far more it can do.

Code
library(plotly)
library(magrittr)
library(tidyquant)
INTC <- tq_get("INTC")
INTC <- tail(INTC, 90)
INTC$ID <- seq.int(nrow(INTC))
INTC %<>%
    mutate(close = round(close, digits = 2))

accumulate_by <- function(dat, var) {
    var <- lazyeval::f_eval(var, dat)
    lvls <- plotly:::getLevels(var)
    dats <- lapply(seq_along(lvls), function(x) {
        cbind(dat[var %in% lvls[seq(1, x)], ], frame = lvls[[x]])
    })
    dplyr::bind_rows(dats)
}

INTC <- INTC %>%
    accumulate_by(~ID)
fig <- INTC %>%
    plot_ly(x = ~ID, y = ~close, frame = ~frame, type = "scatter", mode = "lines",
        fill = "tozeroy", fillcolor = "rgba(73, 26, 201, 0.5)", line = list(color = "rgb(73, 26, 201)"),
        text = ~paste("Date: ", date, "<br>Close: $", close), hoverinfo = "text")
fig <- fig %>%
    layout(title = "Intel Stock Closing Price: Last 90 Days", yaxis = list(title = "Close",
        range = c(0, 50), zeroline = F, tickprefix = "$"), xaxis = list(title = "Day",
        range = c(0, 90), zeroline = F, showgrid = F), margin = list(t = 120))
fig <- fig %>%
    animation_opts(frame = 100, transition = 0, redraw = FALSE)
fig <- fig %>%
    animation_slider(currentvalue = list(prefix = "Day "))
fig

The Crosstalk Idea

Image from book

Some Crosstalk

datatables and crosstalk

From the R javascript book

A Very Simple Example

The trick is shared.

Code
library(DT)
library(plotly)
library(crosstalk)

shared <- SharedData$new(cars)

bscols(plot_ly(shared, x = ~speed, y = ~dist), datatable(shared, width = "100%"))

Pizza on the blog….