perspectiveR provides an R interface to the FINOS Perspective library, a high-performance WebAssembly-powered data visualization engine. It offers interactive pivot tables, cross-tabulations, and multiple chart types that run entirely in the browser.
The simplest usage is to pass a data frame directly:
This opens a fully interactive viewer with a settings panel where you can:
You can set an initial configuration programmatically:
perspective(mtcars,
group_by = "cyl",
columns = c("mpg", "hp", "wt"),
plugin = "Y Bar",
theme = "Pro Dark"
)Users can still modify the view interactively even after initial configuration.
"Datagrid" — interactive data grid (default)"Y Bar" / "X Bar" — vertical / horizontal
bar charts"Y Line" — line chart"X/Y Line" — line chart with explicit X axis"Y Area" — area chart"Y Scatter" / "XY Scatter" — scatter
plots"Treemap" — treemap"Sunburst" — sunburst chart"Heatmap" — heatmapFor datasets with 100k+ rows, use Arrow IPC serialization for better performance:
perspectiveR includes full Shiny support with a proxy interface for streaming updates:
library(shiny)
ui <- fluidPage(
perspectiveOutput("viewer", height = "600px"),
actionButton("add", "Add Data")
)
server <- function(input, output, session) {
output$viewer <- renderPerspective({
perspective(mtcars, plugin = "Y Bar", group_by = "cyl")
})
observeEvent(input$add, {
proxy <- perspectiveProxy(session, "viewer")
new_data <- mtcars[sample(nrow(mtcars), 5), ]
psp_update(proxy, new_data)
})
# Capture user's interactive config changes
observeEvent(input$viewer_config, {
message("User changed config: ", str(input$viewer_config))
})
}
shinyApp(ui, server)psp_update(proxy, data) — append new rows (upserts when
table has an index)psp_replace(proxy, data) — replace all datapsp_clear(proxy) — clear all rowspsp_restore(proxy, config) — apply a configpsp_reset(proxy) — reset to defaultspsp_remove(proxy, keys) — remove rows by primary key
(indexed tables only)psp_export(proxy, format) — export data as JSON, CSV,
columns, or Arrow (supports windowed export)psp_save(proxy) — retrieve current viewer statepsp_on_update(proxy, enable) — subscribe/unsubscribe to
data change eventspsp_schema(proxy) — get table schema (column names and
types)psp_size(proxy) — get table row countpsp_columns(proxy) — get table column namespsp_validate_expressions(proxy, expressions) — validate
expression stringsWhen using multiple filters, you can control how they are combined
using filter_op:
# Match rows where Species is "setosa" OR Sepal.Length > 6
perspective(iris,
filter = list(
c("Species", "==", "setosa"),
c("Sepal.Length", ">", "6")
),
filter_op = "or"
)The default is "and" (all filters must match). Set
filter_op = "or" to match rows that satisfy any filter.
Use the limit parameter to create a rolling-window table
that automatically drops the oldest rows when new rows are added beyond
the limit:
Note that limit and index are mutually
exclusive.
Use the index parameter to create a keyed table. When an
index is set, psp_update() performs upserts—rows with
matching keys are updated instead of appended—and
psp_remove() can delete rows by key.
Request the current view’s data from the browser:
proxy <- perspectiveProxy(session, "viewer")
psp_export(proxy, format = "csv")
# Result arrives asynchronously:
observeEvent(input$viewer_export, {
cat("Format:", input$viewer_export$format, "\n")
cat("Data:", input$viewer_export$data, "\n")
})Supported formats: "json", "csv",
"columns", "arrow" (base64-encoded).
Retrieve the current viewer configuration and restore it later:
Subscribe to table data changes to react when data is updated:
Query the table for its schema, size, or column names:
proxy <- perspectiveProxy(session, "viewer")
# Get column types
psp_schema(proxy)
observeEvent(input$viewer_schema, {
str(input$viewer_schema) # list(col1 = "float", col2 = "string", ...)
})
# Get row count
psp_size(proxy)
observeEvent(input$viewer_size, {
message("Table has ", input$viewer_size, " rows")
})
# Get column names
psp_columns(proxy)
observeEvent(input$viewer_columns, {
message("Columns: ", paste(input$viewer_columns, collapse = ", "))
})Export a subset of rows/columns by specifying a window:
Check whether expression strings are valid before applying them:
Set the visual theme with the theme parameter:
perspective(mtcars, theme = "Pro Dark")
perspective(mtcars, theme = "Dracula")
perspective(mtcars, theme = "Gruvbox Dark")Available themes: "Pro Light" (default),
"Pro Dark", "Monokai",
"Solarized Light", "Solarized Dark",
"Vaporwave", "Dracula",
"Gruvbox", "Gruvbox Dark".