GitHub

Stat Tools for End Users

Basic and custom statistical tools designed with end users in mind. Functions have optimized defaults, produce decluttered and informative output that is self-explanatory, and generate publication-ready results in one line of code.

Installation

# CRAN (when available)
install.packages("statuser")
# Or pin a version with groundhog
groundhog::groundhog.library("statuser", date)

Overview

Same organization as help(statuser):

Basic Stats (improved)

  • lm2() — like lm(), with robust SE and much more informative output
  • t.test2() — like t.test(), decluttered, and more informative output
  • table2() — like table(), showing variable names, and with proportions & chi2 built in
  • desc_var() — descriptive statistics for variables (optional, by group(s))

Custom tools from papers by Uri Simonsohn

  • twolines() — two-lines test for U-shapes (Simonsohn 2018)
  • interprobe() — probe and visualize nonlinear interactions (Simonsohn 2024; Montealegre & Simonsohn 2026)
  • stimulus.plot() — stimulus plots for matched/treated-stimulus designs (Simonsohn, Montealegre, & Evangelidis 2025)
  • stimulus.beeswarm() — beeswarm plots for compared-stimulus designs (Simonsohn, Montealegre, & Evangelidis 2025)

Graphing

  • scatter.gam() — scatter plot for x & y, with fitted GAM line y = f(x)
  • plot_cdf() — empirical cumulative distribution functions (optional, by group)
  • plot_density() — density functions (optional, by group)
  • plot_freq() — frequency of observed values (optional, by group)
  • plot_means() — barplot of means with confidence intervals and (optionally) tests; see also stimulus.plot() for per-stimulus plots
  • plot_gam() — fitted GAM values for a focal predictor
  • text2() — like text() with horizontal alignment and background color

Formatting

  • format_pvalue() — format p-values for display
  • var_labels() — get/set variable labels (as base-R "label" attributes)
  • message2() — print colored messages to console
  • resize_images() — resize images (SVG, PDF, EPS, JPG, PNG, etc.) to PNG with specified width

Miscellaneous

  • clear() — clear environment, console, and all graphics devices
  • list2() — like list(), but unnamed objects are automatically named
  • convert_to_sql() — convert CSV files to SQL INSERT statements

Examples

Basic Stats (improved)

lm2(): like lm(), with robust SE and much more informative output

Uses estimatr for robust and clustered errors. Notes via lm2_notes() after printing.

lm2(mpg ~ wt + hp, data = mtcars)
lm2(mpg ~ wt + hp, data = mtcars, se_type = "HC2")
lm2_notes()
t.test2(): like t.test(), decluttered, and more informative output
men <- rnorm(100, mean = 5, sd = 1)
women <- rnorm(100, mean = 4.8, sd = 1)
t.test2(men, women)
data <- data.frame(y = rnorm(100), group = rep(c("A", "B"), 50))
t.test2(y ~ group, data = data)
table2(): like table(), showing variable names, with proportions & chi2 built in
df <- data.frame(
  group = c("A", "A", "B", "B", "A"),
  status = c("X", "Y", "X", "Y", "X")
)
table2(df$group, df$status)
table2(df$group, df$status, prop = "row", chi = TRUE)
desc_var(): descriptive statistics for variables (optional, by group(s))
df <- data.frame(score = rnorm(100), condition = rep(c("Control", "Treatment"), 50))
desc_var(score ~ condition, data = df)

Custom tools from papers by Uri Simonsohn

twolines(): two-lines test for U-shapes (Simonsohn 2018)

Implements the two-lines test (Simonsohn, 2018).

Reference: Simonsohn, U. (2018). Two lines: A valid alternative to the invalid testing of U-shaped relationships with quadratic regressions. Advances in Methods and Practices in Psychological Science, 1(4), 538–555. https://doi.org/10.1177/2515245918805755

set.seed(123)
x <- rnorm(100)
y <- -x^2 + rnorm(100)
data <- data.frame(x = x, y = y)
twolines(y ~ x, data = data)
# With covariates, suppress Robin Hood details, or save PNG
twolines(y ~ x + z, data = data, quiet = TRUE)
twolines(y ~ x, data = data, pngfile = "twolines_plot.png")
interprobe(): probe and visualize nonlinear interactions

Estimates or accepts a model, then plots simple slopes and Johnson–Neyman curves. Default engine is GAM; also supports linear models, supplied fits, and lm2().

References: Simonsohn, U. (2024). AMPPS. https://doi.org/10.1177/25152459231207787

interprobe(x = "predictor", z = "moderator", y = "outcome", data = df)
interprobe(x = "predictor", z = "moderator", y = "outcome", data = df, model = "linear")
stimulus.plot(): stimulus plots for matched/treated-stimulus designs

Reference: Simonsohn, U., Montealegre, A., & Evangelidis, I. (2025). JPSP, 129(1), 71–90. https://doi.org/10.1037/pspa0000449

stimulus.plot(
  data = df, dv = "score", stimulus = "item", condition = "cond",
  plot.type = "means", watermark = FALSE
)
stimulus.plot(
  data = df, dv = "score", stimulus = "item", condition = "cond",
  plot.type = "effects", participant = "id", simtot = 500, seed = 2024
)
clear_stimulus_cache()
stimulus.beeswarm(): beeswarm plots for compared-stimulus designs
stimulus.beeswarm(
  data = df, dv = "score", stimulus = "stim_id", condition = "cond",
  simtot = 500, watermark = FALSE
)

Graphing

scatter.gam(): scatter plot for x & y, with fitted GAM line
x <- rnorm(100)
y <- 2 * x + rnorm(100)
scatter.gam(x, y)
scatter.gam(y ~ x, data = data.frame(x, y), data.dots = TRUE)
plot_cdf(): ECDFs by group
y <- rnorm(100)
x <- rep(c("A", "B"), 50)
plot_cdf(y ~ x)
plot_cdf(y ~ x, col = c("red", "blue"), order = c("B", "A"))
plot_density(): Densities by group
plot_density(y ~ x)
plot_density(y ~ x, col = c("red", "blue"), show.means = FALSE, order = -1)
plot_freq(): Frequency plot without binning
plot_freq(c(1, 1, 2, 2, 2, 5, 5))
df <- data.frame(
  value = c(1, 1, 2, 2, 2, 5, 5),
  group = c("A", "A", "A", "B", "B", "A", "B")
)
plot_freq(value ~ group, data = df, order = c("B", "A"))
plot_freq(value ~ group, data = df, freq = FALSE, legend.title = "Treatment")
plot_means(): barplot of means with CIs and (optionally) tests

Up to three grouping factors; optional clustered SEs and custom comparisons. See stimulus.plot() for per-stimulus plots.

df <- data.frame(y = rnorm(100), group = rep(c("A", "B"), 50))
plot_means(y ~ group, data = df, quiet = TRUE)
df2 <- data.frame(
  y = rnorm(200),
  x1 = rep(c("A", "B"), 100),
  x2 = rep(c("X", "Y"), each = 100)
)
plot_means(y ~ x1 + x2, data = df2)
plot_gam(): GAM partial effect with optional distribution panel
library(mgcv)
model <- gam(mpg ~ s(hp) + s(wt) + factor(cyl), data = mtcars)
plot_gam(model, "hp", plot2 = "auto")
plot_gam(model, "hp", plot2 = "freq", quantile.others = 25)
text2(): like text() with horizontal alignment and background color
plot(1:10, 1:10, type = "n")
text2(2, 8, "Left", align = "left", bg = "lightblue")
text2(5, 8, "Center", align = "center", bg = "lightgreen")
text2(8, 8, "Right", align = "right", bg = "lightyellow")
text2(5, 5, "Red text", col = "red", bg = "white")

Formatting

format_pvalue(): format p-values for display
format_pvalue(0.05)
format_pvalue(0.0001, include_p = TRUE)
var_labels(): get/set variable labels
df <- data.frame(x = 1:3, y = 4:6)
var_labels(df) <- c("Variable X", "Variable Y")
var_labels(df)
message2(): print colored messages to console
message2("Note", col = "cyan", font = 2)
resize_images(): resize images to PNG at a set width
resize_images("path/to/image.svg", width = 800)
resize_images("path/to/images", width = c(800, 1200, 600))

Miscellaneous

clear(): clear environment, console, and graphics devices
clear()  # first run may prompt for one-time permission
list2(): like list(), auto-named objects
list2(x, y, z)
convert_to_sql(): CSV to SQL INSERT statements
convert_to_sql("data.csv", "data.sql")

Dependencies

Imports: mgcv, marginaleffects, rsvg, magick, sandwich, lmtest, lmerTest, digest, beeswarm, utils

Suggested (optional features): estimatr (lm2()), testthat, crayon, quantreg, broom, modelsummary

Author

Uri Simonsohnurisohn@gmail.comhttps://github.com/urisohn/statuser

License

GPL-3

Version

CRAN release: 0.3.0 (stimulus plots, lm2_notes(), Cohen's d in t.test2(), and related fixes). Development version may be ahead of CRAN.

Read the original on github.com ↗