Launches an interactive Shiny gadget containing an infinite 2D canvas with mouse-wheel zoom, pan, draggable table cards, interactive column mapping, discrepancy recoding, and LLM-assisted tidyverse code generation.
Usage
sideview(
...,
title = "Sideview Canvas",
viewer = if (requireNamespace("rstudioapi", quietly = TRUE) &&
rstudioapi::isAvailable()) {
shiny::dialogViewer("Sideview Canvas", width =
1400, height = 900)
} else {
shiny::paneViewer(minHeight = 500)
},
theme = "auto",
state = NULL,
env = parent.frame(),
run = interactive()
)Arguments
- ...
Arbitrary table objects (
data.frame,tibble,matrix,table,gt,flextable,htmlwidgets), named or unnamed.- title
Title for the gadget viewer.
- viewer
Shiny viewer gadget display mode (e.g.
shiny::paneViewer(),shiny::dialogViewer(),shiny::browserViewer()), or a character shorthand ("browser","dialog", or"pane"). Default isshiny::dialogViewer()(width 1400, height 900) when RStudio is available, otherwiseshiny::paneViewer().- theme
Canvas theme:
"auto"(default; follows the RStudio editor theme),"light","dark", ansv_theme()or abslib::bs_theme().- state
A saved workspace to restore: a
sideview_state(seenew_sideview_state()) or the path to a file written by the toolbar's Save button orsv_save_state(). Card positions and sizes, zoom and pan, sorts, filters, joins and the pipeline come back; cards are matched to tables by name.- env
Environment where Run in R evaluates the generated code and stores its result (as
sv_resultunless you name it). Defaults to the environmentsideview()is called from, which is your workspace when you call it from the console.- run
Logical; if
TRUE, launches the interactive gadget viashiny::runGadget(). IfFALSE, returns theshiny.appobjdefinition without launching (useful for testing or embedding). Defaults tointeractive().
Value
If run = TRUE, the generated code (invisibly) when you click
Done, or NULL after Cancel or closing the window.
If run = FALSE, returns a shiny.appobj with the normalized cards attached.
Big tables (arrow and duckdb)
Arrow tables, datasets and queries and duckdb tables (dplyr::tbl()) go on
the canvas as cards that show a 50-row preview. When the duckdb, dbplyr and
DBI packages are installed, sorting, filtering, scrolling, the join check,
the column inspector and the codebook use the whole table: duckdb runs them
and only summaries and row windows come back into R. The table is never
collected. Without duckdb, or when the link to a table is lost, the card
says "First 50 of N rows" and the checks use the preview.
Generated code stays lazy and ends in one collect(). Known differences
from an in-memory card:
"Contains" on a number matches its text. The grid filter drops a trailing
.0, but in generated code duckdb writes a double as"130.0"where R writes"130", and float noise or scientific notation can differ. The generated filter is a literal match,stringr::str_detect(col, "<escaped literal>").POSIXct values at exactly midnight, and
-0, can print differently.Join keys of different types compare as text, and double keys compare exactly.
Arrow time-zone offsets are computed for 1900 to 2100; local times outside that range may be off. duckdb
TIMESTAMPTZcolumns show in UTC.Joining arrow with duckdb copies the arrow side into a duckdb temporary table (
arrow::to_duckdb()thendplyr::compute()), which costs memory; a data frame joined into duckdb is copied assideview_<table>.duckdb 1.4.3 can crash when it scans an arrow factor column that contains
NA. sideview decodes such columns itself, but generated code that callsarrow::to_duckdb()on one may hit it: convert the factor to character first.
If Run in R fails on a lazy pipeline, the message suggests moving
collect() above the step that needs R.
Keyboard and navigation
Single-key shortcuts work when the canvas has the keyboard and you are not
typing: F fit all cards, 0 reset zoom, +/- zoom, M show or hide
the minimap, D the drawer, T light/dark, / the AI prompt and ? the
full list. Ctrl+K finds a card or column, Ctrl+Z/Ctrl+Y undo and
redo a pipeline step, and Esc cancels a connection or closes a popover.
Double-click a card title, a minimap rectangle or a search result to zoom
to that card.
Options
sideview.session_graceSeconds the gadget waits after its last browser session closes before stopping (default
5), so reloading the page does not end the app.sideview.llm_backend"ollama"(default, or theSIDEVIEW_LLM_BACKENDvariable) or"openai"for any OpenAI-compatible server.sideview.llm_modelModel name. Defaults to
SIDEVIEW_OLLAMA_MODELor"llama3.2"for Ollama, andSIDEVIEW_OPENAI_MODELor"gpt-4o-mini"otherwise.sv_llm_models()lists what is available.sideview.llm_endpointBase URL. Defaults to
OLLAMA_HOSTorhttp://localhost:11434, andOPENAI_BASE_URLorhttps://api.openai.com/v1.sideview.llm_api_keyAPI key for OpenAI-compatible servers (default: the
OPENAI_API_KEYvariable).sideview.llm_thinkTRUElets Ollama reasoning models "think" before answering. DefaultFALSE, so they answer promptly.
Only schema summaries (column names, types and simple profiles) are sent to the model, never raw rows.
Examples
if (interactive()) {
sideview(mtcars, iris)
}
