RaukR 2026 • Data Science With R
Roy Francis
18-Aug-2026
Design principles

squirrels <- squirrels |>
mutate(
observation_date = as.Date(as.character(date), format = "%m%d%Y"),
fur_color = factor(
coalesce(primary_fur_color, "Unknown"),
levels = c("Gray", "Cinnamon", "Black", "Unknown")
),
age_group = case_when(
age %in% c("Adult", "Juvenile") ~ age,
TRUE ~ "Unknown"
),
above_ground_sighter_measurement = as.integer(
if_else(above_ground_sighter_measurement == "FALSE", "0", above_ground_sighter_measurement)
),
location = coalesce(location, "Unknown"),
shift = factor(shift, levels = c("AM", "PM"))
)
fur_colors <- c(
Gray = "#7A7D80",
Cinnamon = "#B65A24",
Black = "#2B2B2B",
Unknown = "#BDBDBD"
)
squirrel_points <- squirrels |>
filter(!is.na(long), !is.na(lat)) |>
mutate(
point_id = row_number(),
hover = paste0(
"<b>", unique_squirrel_id, "</b><br>",
"Fur: ", fur_color, "<br>",
"Age: ", age_group, "<br>",
"Shift: ", shift, "<br>",
"Location: ", location
)
)
fur_counts <- squirrels |>
count(fur_color, sort = TRUE)
squirrel_preview <- squirrels |>
select(unique_squirrel_id, shift, age_group, fur_color, location, long, lat) |>
slice_head(n = 15)
behaviour_names <- c(
"running", "chasing", "climbing", "eating", "foraging", "kuks",
"quaas", "moans", "tail_flags", "tail_twitches", "approaches",
"indifferent", "runs_from"
)DT, reactable, gtplotly, highcharter, dygraphs, ggiraph, echarts4rleaflet, mapgl, mapview, mapdeck, tmapvisNetwork, networkD3, DiagrammeRcrosstalkDTreactablegtgt is primarily for publication-ready tables, with a concise interactive mode.
ggiraph adds browser interactions to familiar ggplot2 geoms.
library(ggiraph)
ggiraph_plot <- ggplot(
squirrel_points,
aes(long, lat, color = fur_color)
) +
geom_point_interactive(
aes(tooltip = hover),
alpha = 0.65,
size = 1.8
) +
scale_color_manual(values = fur_colors) +
labs(x = "Longitude", y = "Latitude", color = "Fur color") +
theme_minimal()
girafe(ggobj = ggiraph_plot)plot_ly() builds native traces and layoutsggplotly() provides a quick bridge from ggplot2plot_ly(
fur_counts,
x = ~fur_color,
y = ~n,
type = "bar",
text = ~paste0(fur_color, ": ", n),
hoverinfo = "text",
marker = list(
color = unname(fur_colors[as.character(fur_counts$fur_color)])
),
width = 360,
height = 430
) |>
layout(
title = "Primary fur color counts",
xaxis = list(title = "Fur color"),
yaxis = list(title = "Observations")
)Use barmode = "stack" for composition and "group" for direct comparison.
A range slider exposes a detailed time window without rebuilding the chart.
behaviour_by_shift <- squirrels |>
select(shift, all_of(behaviour_names)) |>
filter(!is.na(shift)) |>
pivot_longer(
-shift,
names_to = "behaviour",
values_to = "observed"
) |>
group_by(shift, behaviour) |>
summarise(
proportion = mean(observed),
.groups = "drop"
) |>
pivot_wider(
names_from = shift,
values_from = proportion
)
plot_ly(
x = c("AM", "PM"),
y = behaviour_by_shift$behaviour,
z = as.matrix(select(behaviour_by_shift, AM, PM)),
type = "heatmap",
colors = "YlGnBu"
)plot_ly(
squirrel_points,
type = "scattermapbox",
lon = ~long, lat = ~lat,
color = ~fur_color,
colors = unname(fur_colors),
text = ~hover, hoverinfo = "text",
marker = list(size = 7, opacity = 0.65)
) |>
layout(mapbox = list(
style = "open-street-map",
center = list(
lon = -73.9654,
lat = 40.7829
),
zoom = 12.5
))linked_points <- squirrel_points |>
mutate(point_id = row_number()) |>
highlight_key(~point_id)
coordinates <- plot_ly(linked_points,
x = ~long, y = ~lat, color = ~fur_color,
type = "scatter", mode = "markers",
colors = unname(fur_colors)
)
height <- plot_ly(linked_points,
x = ~hectare_squirrel_number,
y = ~above_ground_sighter_measurement,
color = ~fur_color, type = "scatter",
mode = "markers",
showlegend = FALSE,
colors = unname(fur_colors)
)
highlight(subplot(coordinates, height),
on = "plotly_selected", dynamic = TRUE)Use ggplotly() for quick hover and zoom. Use native Plotly traces when interaction needs precise control.
hchart() is concise for familiar data shapeshighchart() plus hc_add_series() gives explicit series controlhchart()hchart() turns a data frame and mapped columns into a chart quickly.
These options layer chart behaviour independently from the series definition.
A coordinate scatterplot is a lightweight geographic fallback when a basemap is unnecessary.
plot_ly() builds traces; layout() controls presentation; highlight() links viewshchart() is concise; highchart() plus hc_add_series() is explicit and extensibleggplot2 bridgeR version 4.5.3 (2026-03-11)
Platform: x86_64-conda-linux-gnu
Running under: Ubuntu 26.04 LTS
Matrix products: default
BLAS/LAPACK: /home/roy/miniforge3/envs/r-4.5/lib/libopenblasp-r0.3.33.so; LAPACK version 3.12.0
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
time zone: Europe/Stockholm
tzcode source: system (glibc)
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] gt_1.3.0 reactable_0.4.5 DT_0.34.0 highcharter_0.9.5
[5] plotly_4.12.0 ggiraph_0.9.6 ggplot2_4.0.3 readr_2.2.0
[9] tidyr_1.3.2 dplyr_1.2.1
loaded via a namespace (and not attached):
[1] gtable_0.3.6 bslib_0.11.0 xfun_0.59
[4] htmlwidgets_1.6.4 rlist_0.4.6.2 lattice_0.22-9
[7] tzdb_0.5.0 crosstalk_1.2.2 vctrs_0.7.3
[10] tools_4.5.3 generics_0.1.4 curl_7.1.0
[13] tibble_3.3.1 xts_0.14.2 pkgconfig_2.0.3
[16] data.table_1.18.4 RColorBrewer_1.1-3 S7_0.2.2
[19] assertthat_0.2.1 lifecycle_1.0.5 compiler_4.5.3
[22] farver_2.1.2 stringr_1.6.0 httpuv_1.6.17
[25] fontquiver_0.2.1 fontLiberation_0.1.0 sass_0.4.10
[28] htmltools_0.5.9 yaml_2.3.12 lazyeval_0.2.3
[31] later_1.4.8 jquerylib_0.1.4 pillar_1.11.1
[34] MASS_7.3-65 cachem_1.1.0 mime_0.13
[37] fontBitstreamVera_0.1.1 tidyselect_1.2.1 digest_0.6.39
[40] stringi_1.8.7 purrr_1.2.2 labeling_0.4.3
[43] fastmap_1.2.0 grid_4.5.3 cli_3.6.6
[46] magrittr_2.0.5 broom_1.0.13 reactR_0.6.1
[49] withr_3.0.3 promises_1.5.0 gdtools_0.5.1
[52] scales_1.4.0 backports_1.5.1 lubridate_1.9.5
[55] timechange_0.4.0 TTR_0.24.4 rmarkdown_2.31
[58] httr_1.4.8 quantmod_0.4.29 otel_0.2.0
[61] zoo_1.8-15 hms_1.1.4 shiny_1.14.0
[64] evaluate_1.0.5 knitr_1.51 viridisLite_0.4.3
[67] rlang_1.3.0 Rcpp_1.1.1-1.1 xtable_1.8-8
[70] glue_1.8.1 xml2_1.6.0 jsonlite_2.0.0
[73] R6_2.6.1 systemfonts_1.3.2 fs_2.1.0