The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.

Introduction to perspectiveR

Overview

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.

Quick Start

library(perspectiveR)

The simplest usage is to pass a data frame directly:

perspective(mtcars)

This opens a fully interactive viewer with a settings panel where you can:

Configuration

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.

Available Chart Types

Filtering and Sorting

perspective(iris,
  filter = list(c("Species", "==", "setosa")),
  sort = list(c("Sepal.Length", "desc"))
)

Computed Expressions

perspective(mtcars,
  expressions = c('"hp" / "wt"'),
  columns = c("mpg", "hp", "wt", '"hp" / "wt"')
)

Arrow IPC for Large Datasets

For datasets with 100k+ rows, use Arrow IPC serialization for better performance:

# Requires the arrow package
big_data <- data.frame(
  x = rnorm(100000),
  y = rnorm(100000),
  group = sample(letters, 100000, replace = TRUE)
)
perspective(big_data, use_arrow = TRUE)

Shiny Integration

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)

Proxy Functions

Filter Operator

When 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.

Rolling Window Tables

Use the limit parameter to create a rolling-window table that automatically drops the oldest rows when new rows are added beyond the limit:

# Keep only the last 100 rows
perspective(streaming_data, limit = 100)

Note that limit and index are mutually exclusive.

Indexed Tables

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.

# Create an indexed table keyed on "cyl"
perspective(mtcars, index = "cyl", plugin = "Datagrid")

# In a Shiny server:
proxy <- perspectiveProxy(session, "viewer")
psp_update(proxy, updated_rows)   # upserts by "cyl"
psp_remove(proxy, keys = c(4, 8)) # remove rows where cyl == 4 or 8

Exporting Data

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).

Saving and Restoring State

Retrieve the current viewer configuration and restore it later:

proxy <- perspectiveProxy(session, "viewer")

# Save current state
psp_save(proxy)
observeEvent(input$viewer_state, {
  saved <- input$viewer_state
  # Later, restore it:
  psp_restore(proxy, saved)
})

Update Notifications

Subscribe to table data changes to react when data is updated:

proxy <- perspectiveProxy(session, "viewer")
psp_on_update(proxy, enable = TRUE)

observeEvent(input$viewer_update, {
  info <- input$viewer_update
  message("Update at ", info$timestamp, " from ", info$source)
})

# To unsubscribe:
psp_on_update(proxy, enable = FALSE)

Table Metadata

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 = ", "))
})

Windowed Export

Export a subset of rows/columns by specifying a window:

proxy <- perspectiveProxy(session, "viewer")

# Export only the first 50 rows
psp_export(proxy, format = "json", start_row = 0, end_row = 50)

# Export rows 100-200, columns 0-3
psp_export(proxy, format = "csv",
  start_row = 100, end_row = 200,
  start_col = 0, end_col = 3
)

Validating Expressions

Check whether expression strings are valid before applying them:

proxy <- perspectiveProxy(session, "viewer")
psp_validate_expressions(proxy, c('"hp" / "wt"', '"invalid_col" + 1'))

observeEvent(input$viewer_validate_expressions, {
  result <- input$viewer_validate_expressions
  # Contains validation info for each expression
  str(result)
})

Themes

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".

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.