library(plotly)
#install.packages("dygraphs")
library(dygraphs)
library(tidyverse)
library(tsibble)
library(ggiraph)Interactive Data Visualisation
R packages
Data packages
library(covid19srilanka)
library(palmerpenguins)
Attaching package: 'palmerpenguins'
The following objects are masked from 'package:datasets':
penguins, penguins_raw
Dygraphs in Time Series
Data preprocessing
data(covid.cases)
head(covid.cases)# A tibble: 6 × 3
Date Type Count
<date> <chr> <dbl>
1 2020-03-29 Confirmed 115
2 2020-03-29 Recovered 10
3 2020-03-29 Deaths 1
4 2020-03-29 Active 104
5 2020-03-30 Confirmed 120
6 2020-03-30 Recovered 11
library(tsibble)
library(dplyr)
library(tidyr)
# Convert to tsibble
covid.cases <- covid.cases |>
mutate(Date = as.Date(Date)) |>
as_tsibble(index = Date, key = Type)
# Check if the data is regular (e.g., daily, weekly, monthly)
is_regular(covid.cases)[1] TRUE
# Identify the interval
interval(covid.cases)<interval[1]>
[1] 1D
# Fill missing dates (if any) with NA
covid.cases_filled <- covid.cases |>
fill_gaps()
# (Optional) replace missing counts with 0 instead of NA
covid.cases_filled <- covid.cases |>
fill_gaps(Count = 0)Time series plot
Preparing data for dygraphs
# Pivot to wide format for dygraphs
covid_wide <- covid.cases |>
pivot_wider(names_from = Type, values_from = Count)
# Convert to xts (remove Date column and set as rownames)
covid_xts <- xts::xts(covid_wide |> select(-Date), order.by = covid_wide$Date)
head(covid_xts) Active Actives Confirmed Deaths Recovered Date
2020-03-29 104 <NA> 115 1 10 2020-03-29
2020-03-30 108 <NA> 120 1 11 2020-03-30
2020-03-31 104 <NA> 122 2 16 2020-03-31
2020-04-01 123 <NA> 143 2 18 2020-04-01
2020-04-02 124 <NA> 148 3 21 2020-04-02
2020-04-03 125 <NA> 151 4 22 2020-04-03
# Plot with dygraphs
dygraph(covid_xts) |>
dyRangeSelector() |> # adds interactive date range selector
dyOptions(stackedGraph = FALSE) |>
dyLegend(show = "follow")ggplotly
g <- ggplot(covid.cases, aes(x = Date, y = Count, group = Type, color=Type)) +
geom_line(alpha = 0.4)
ggplotly(g, tooltip = c("Type"))using plotly
# Basic plotly line plot
plot_ly(
data = covid.cases,
x = ~Date,
y = ~Count,
color = ~Type, # group lines by 'Type'
type = "scatter",
mode = "lines",
line = list(width = 2, dash = "solid"), # optional styling
opacity = 0.4 # mimic ggplot alpha
) %>%
layout(
title = "COVID Cases Over Time",
xaxis = list(title = "Date"),
yaxis = list(title = "Count")
)Scatterplot
plotly: ggplotly
p1 <- penguins |>
ggplot(aes(x = bill_length_mm, y = bill_depth_mm,
color = species, shape = species)) +
geom_point(size = 2) +
geom_smooth(method = "lm", formula = "y ~ x") +
labs(x = "Bill length (mm)", y = "Bill width (mm)") +
theme_minimal()
p1Warning: Removed 2 rows containing non-finite outside the scale range
(`stat_smooth()`).
Warning: Removed 2 rows containing missing values or values outside the scale range
(`geom_point()`).

ggplotly(p1)Warning: Removed 2 rows containing non-finite outside the scale range
(`stat_smooth()`).
plotly: plotly
penguins |>
plot_ly(x = ~bill_length_mm, y = ~flipper_length_mm,
color = ~species, symbol = ~species,
type = "scatter", mode = "markers", marker = list(size = 10)) |>
layout(
plot_bgcolor = 'white',
xaxis = list(title = "Bill Length (mm)", zeroline = FALSE, ticklen = 5),
yaxis = list(title = "Flipper Length (mm)", zeroline = FALSE, ticklen = 5),
title = "Bill length vs. bill width"
)Warning: Ignoring 2 observations
ggiraph
p2 <- penguins |>
ggplot(aes(x = bill_length_mm, y = bill_depth_mm,
color = species, shape = species)) +
geom_point_interactive(
aes(tooltip = paste("bill_length_mm:", bill_length_mm, "<br>",
"bill_depth_mm:", bill_depth_mm)),
size = 2
) +
geom_smooth_interactive(method = "lm", formula = "y ~ x")
girafe(ggobj = p2)Warning: Removed 2 rows containing non-finite outside the scale range
(`stat_smooth()`).
Warning: Removed 2 rows containing missing values or values outside the scale range
(`geom_interactive_point()`).
Bar graph
ggiraph
p3 <- penguins |>
ggplot(aes(x = island)) +
geom_bar_interactive(aes(tooltip = paste("count:", after_stat(count)),
data_id = island))
girafe(ggobj = p3)plotly:plotly
penguins |>
count(island) |>
plot_ly(data = _, x = ~island, y = ~n, type = "bar") |>
layout(barmode = 'stack')plotly:ggplotly
p3 <- penguins |>
ggplot(aes(x = island)) +
geom_bar()
ggplotly(p3)Your turn: Draw histogram for flipper length
Faceting with interactive plots
p4 <- penguins |>
ggplot(aes(x = bill_length_mm, y = flipper_length_mm)) +
geom_point_interactive(
aes(color = species, shape = species,
tooltip = paste("bill_length_mm:", bill_length_mm, "<br>",
"flipper_length_mm:", flipper_length_mm, "<br>",
"species:", species))
) +
facet_wrap(~island)
girafe(ggobj = p4)Warning: Removed 2 rows containing missing values or values outside the scale range
(`geom_interactive_point()`).
p5 <- penguins |>
ggplot(aes(x = bill_length_mm, y = flipper_length_mm)) +
geom_point(aes(color = species, shape = species)) +
facet_wrap(~island)
ggplotly(p5)penguins |>
group_by(island) |>
group_map(~{
plot_ly(data = ., x = ~bill_length_mm, y = ~flipper_length_mm,
color = ~species, type = "scatter", mode = "markers")
}, .keep = TRUE) |>
subplot(nrows = 1, shareX = TRUE, shareY = TRUE)Warning: Ignoring 1 observations
Warning: Ignoring 1 observations
Linked interactivity across the subplots
library(dplyr)
library(plotly)
library(palmerpenguins)
# Prepare data with highlight by species
penguins1 <- penguins %>%
highlight_key(~species)
# ---- Plot 1: Flipper length vs Body mass ----
fig1 <- plot_ly(
data = penguins1,
x = ~flipper_length_mm,
y = ~body_mass_g,
type = "scatter",
mode = "markers",
color = ~species
)
# ---- Plot 2: Bill length vs Bill depth ----
fig2 <- plot_ly(
data = penguins1,
x = ~bill_length_mm,
y = ~bill_depth_mm,
type = "scatter",
mode = "markers",
color = ~species
)
# ---- Combine both side by side ----
subplot(fig1, fig2, nrows = 1, shareY = FALSE, titleX = TRUE, titleY = TRUE)Warning: Ignoring 2 observations
Warning: Ignoring 2 observations
library(dplyr)
library(plotly)
library(palmerpenguins)
# Add a unique ID for each row
penguins1 <- penguins %>%
mutate(id = row_number()) %>%
highlight_key(~id)
# ---- Plot 1: Flipper length vs Body mass ----
fig1 <- plot_ly(
data = penguins1,
x = ~flipper_length_mm,
y = ~body_mass_g,
type = "scatter",
mode = "markers",
color = ~species
)
# ---- Plot 2: Bill length vs Bill depth ----
fig2 <- plot_ly(
data = penguins1,
x = ~bill_length_mm,
y = ~bill_depth_mm,
type = "scatter",
mode = "markers",
color = ~species
)
# ---- Combine both plots side by side ----
subplot(fig1, fig2, nrows = 1, shareY = FALSE, titleX = TRUE, titleY = TRUE) %>%
highlight(on = "plotly_selected", off = "plotly_doubleclick")Warning: Ignoring 2 observations
Warning: Ignoring 2 observations