From 723ae19b676a0712dbf5727d2b7c9565ee6fd2aa Mon Sep 17 00:00:00 2001 From: Achim Zeileis Date: Mon, 15 Dec 2025 03:51:39 +0100 Subject: [PATCH 1/5] tinyframe() can now handle formulas without variables (e.g., ~ 1 or ~ 0) --- R/tinyformula.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/R/tinyformula.R b/R/tinyformula.R index 56fd546e..29189061 100644 --- a/R/tinyformula.R +++ b/R/tinyformula.R @@ -74,6 +74,8 @@ tinyframe = function(formula, data, drop = FALSE) { ## - formula: (sub-)formula ## - data: model.frame from full formula if (is.null(formula)) return(NULL) - names = sapply(attr(terms(formula), "variables")[-1L], deparse, width.cutoff = 500L) + vars = attr(terms(formula), "variables")[-1L] + if (is.null(vars)) return(NULL) + names = sapply(vars, deparse, width.cutoff = 500L) data[, names, drop = drop] } From e4b53d5db54a58fe520dbcecf84f8ccbbc30de9b Mon Sep 17 00:00:00 2001 From: Achim Zeileis Date: Mon, 15 Dec 2025 03:52:36 +0100 Subject: [PATCH 2/5] support formulas without x-variable such as ~ 0 or ~ 1 or y ~ 1 etc. --- R/tinyplot.R | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/R/tinyplot.R b/R/tinyplot.R index 1073a4c9..2cd5ec81 100644 --- a/R/tinyplot.R +++ b/R/tinyplot.R @@ -1429,13 +1429,15 @@ tinyplot.formula = function( m[[1L]] = quote(stats::model.frame) mf = eval.parent(m) - ## extract x + ## extract x (if any) x = tinyframe(tf$x, mf) xnam = names(x)[[1L]] - if (length(names(x)) != 1L) warning( - paste("formula should specify exactly one x-variable, using:", xnam), + if (!is.null(x)) { + xnam = names(x)[[1L]] + if (length(names(x)) > 1L) warning(paste("formula should specify at most one x-variable, using:", xnam), "\nif you want to use arithmetic operators, make sure to wrap them inside I()") - x = x[[xnam]] + x = x[[xnam]] + } ## extract y (if any) y = tinyframe(tf$y, mf) From 636e832781a9264cb72ab67788ea0a54fa941b5c Mon Sep 17 00:00:00 2001 From: Achim Zeileis Date: Mon, 15 Dec 2025 04:17:39 +0100 Subject: [PATCH 3/5] handle names(x) only if non-NULL --- R/tinyplot.R | 1 - 1 file changed, 1 deletion(-) diff --git a/R/tinyplot.R b/R/tinyplot.R index 2cd5ec81..050b2a61 100644 --- a/R/tinyplot.R +++ b/R/tinyplot.R @@ -1431,7 +1431,6 @@ tinyplot.formula = function( ## extract x (if any) x = tinyframe(tf$x, mf) - xnam = names(x)[[1L]] if (!is.null(x)) { xnam = names(x)[[1L]] if (length(names(x)) > 1L) warning(paste("formula should specify at most one x-variable, using:", xnam), From 06775ae08976f571f85dc0bddb0ad101a66f06c8 Mon Sep 17 00:00:00 2001 From: Achim Zeileis Date: Wed, 4 Feb 2026 03:20:45 +0100 Subject: [PATCH 4/5] handle defaults for cases where x or y is NULL - x = , y = NULL: barplot - x = NULL, y = : barplot - x = NULL, y = !: histogram - x = !, y = NULL: scatterplot against index (previous default) note that the cases with x = NULL necessitate switching settingsx and settings$y axis labels still need fixing --- R/sanitize_type.R | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/R/sanitize_type.R b/R/sanitize_type.R index 6a13516c..dc50fd57 100644 --- a/R/sanitize_type.R +++ b/R/sanitize_type.R @@ -43,10 +43,23 @@ sanitize_type = function(settings) { assert_choice(type, known_types, null.ok = TRUE) if (is.null(type)) { - if (!is.null(x) && (is.factor(x) || is.character(x)) && !(is.factor(y) || is.character(y))) { + if (is.null(x) && !(is.factor(y) || is.character(y))) { + # enforce histogram type for y ~ 1 + settings$x = y + settings$y = NULL + type = type_hist + } else if (is.null(x) && (is.factor(y) || is.character(y))) { + # enforce barplot type for factor(y) ~ 1 + settings$x = y + settings$y = NULL + type = type_barplot + } else if ((is.factor(x) || is.character(x)) && is.null(y)) { + # enforce barplot type for ~ factor(y) + type = type_barplot + } else if (!is.null(x) && (is.factor(x) || is.character(x)) && !(is.factor(y) || is.character(y))) { # enforce boxplot type for y ~ factor(x) type = type_boxplot - } else if (is.factor(y) || is.character(y)) { + } else if (!is.null(x) && (is.factor(y) || is.character(y))) { # enforce spineplot type for factor(y) ~ x type = type_spineplot } else { From c8aa24db95caa68b3fb792f0614b3dc942175deb Mon Sep 17 00:00:00 2001 From: Achim Zeileis Date: Wed, 4 Feb 2026 03:24:08 +0100 Subject: [PATCH 5/5] set xnam/ynam to NULL if x/y are missing --- R/tinyplot.R | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/R/tinyplot.R b/R/tinyplot.R index 050b2a61..22bc1135 100644 --- a/R/tinyplot.R +++ b/R/tinyplot.R @@ -1436,6 +1436,8 @@ tinyplot.formula = function( if (length(names(x)) > 1L) warning(paste("formula should specify at most one x-variable, using:", xnam), "\nif you want to use arithmetic operators, make sure to wrap them inside I()") x = x[[xnam]] + } else { + xnam = NULL } ## extract y (if any) @@ -1445,6 +1447,8 @@ tinyplot.formula = function( if (length(names(y)) > 1L) warning(paste("formula should specify at most one y-variable, using:", ynam), "\nif you want to use arithmetic operators, make sure to wrap them inside I()") y = y[[ynam]] + } else { + ynam = NULL } ## extract by (if any)