Skip to contents

A lightweight Shiny input wrapper around modist: draggable probability distributions that behave like regular Shiny inputs.

shinymodist keeps the default presentation compact and low-noise, while retaining an opt-in style = "modist" mode close to the upstream experience.

Motivation

modist makes probability distributions directly manipulable. shinymodist turns that interaction into a regular Shiny input, so a distribution can become part of the application’s state rather than just a plot.

Bayesian prior elicitation is a natural example: changing an assumption should feel as direct as moving the distribution itself. Here we use two shinymodist inputs for a Normal model with unknown mean and variance:

\[ y_i \mid \mu, \sigma^2 \sim \mathcal{N}(\mu, \sigma^2) \]

\[ \mu \sim \mathcal{N}(m_0, s_0^2), \qquad \sigma^2 \sim \operatorname{InverseGamma}(\alpha_0, \beta_0) \]

After observing data, Bayes’ rule combines the likelihood and both priors:

\[ p(\mu, \sigma^2 \mid y) \propto p(y \mid \mu, \sigma^2)\, p(\mu)\, p(\sigma^2). \]

Drag either prior below, then reveal more real observations from mtcars$mpg. The two panels show how each marginal posterior moves away from — or stays close to — the prior. The posterior is evaluated on a small deterministic grid, keeping the example dependency-free and easy to inspect.

Install

pak::pak("jbkunst/shinymodist")

Basic use

library(shiny)
library(shinymodist)

ui <- bslib::page_sidebar(
  title = "Basic shinymodist input",
  sidebar = bslib::sidebar(
    modist_input(
      "dist",
      family = "normal",
      value = list(mu = 0, sigma = 1)
    )
  ),
  bslib::card(
    bslib::card_header("Reactive value"),
    verbatimTextOutput("value")
  )
)

server <- function(input, output, session) {
  output$value <- renderPrint(input$dist)
}

shinyApp(ui, server)

The input returns the distribution family and its canonical parameters:

list(
  family = "normal",
  mu = 0,
  sigma = 1
)

A fixed visible scale can be supplied when comparisons need a common domain:

modist_input(
  "scores",
  family = "normal",
  value = list(mu = 1, sigma = 1),
  domain = c(-5, 5)
)

Server-side updates use update_modist_input().

Styles and bslib

The default style = "minimal" is intentionally quiet: no grid or toolbar, and its visual accents inherit --bs-primary when used inside a bslib theme.

bslib::page_fluid(
  theme = bslib::bs_theme(primary = "#6f42c1"),
  modist_input("dist")
)

Use style = "modist" to keep the original modist appearance and controls.

The input is responsive by default. A fixed CSS height is available only when the surrounding layout needs it:

modist_input("dist", height = "180px")

The default height = NULL keeps the current aspect-ratio behavior.

Live demos

The pkgdown site exports the package examples with Shinylive, so they run entirely in the browser with webR:

The live examples run entirely in the browser with Shinylive and webR.

Distribution families

The wrapper exposes all distribution families bundled by modist:

  • Normal, Beta, Gamma and Student t
  • Exponential, Half Normal and Log Normal
  • Cauchy, Laplace and Logistic
  • Weibull, Half Student t and Chi-squared
  • Inverse Gamma and Kumaraswamy

All families use the same modist_input() API. See the distribution gallery for a compact fillable grid of every supported family.

WebAssembly and Shinylive

The examples can run entirely in the browser with Shinylive and webR. WebAssembly compatibility is checked in CI and supported in package releases.

Credits

shinymodist wraps the JavaScript distribution widgets from William Dean’s modist, distributed under the MIT License.

The compact Shiny-input philosophy is also inspired by Carson Sievert’s histoslider.

License

MIT