From 52afd68312bb00e93132bdd0c216e10362af264f Mon Sep 17 00:00:00 2001 From: Achim Zeileis Date: Sun, 22 Mar 2026 12:24:53 +0100 Subject: [PATCH 1/5] add tinyplot() method for 'ts' time series objects --- R/tinyplot.ts.R | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 R/tinyplot.ts.R diff --git a/R/tinyplot.ts.R b/R/tinyplot.ts.R new file mode 100644 index 00000000..82625b9f --- /dev/null +++ b/R/tinyplot.ts.R @@ -0,0 +1,69 @@ +#' tinyplot Method for Plotting ts Objects (Time Series) +#' +#' @description Convenience interface for visualizing ts objects +#' (time sereis with tinyplot. +#' +#' @details Internally the time series object is converted to a long +#' data frame with columns `Time` (time index), `Value` (observations), +#' and `Series` (factor with column labels). Depending on the settings +#' of `facet` this data frame is visualized either with the formula +#' `Value ~ Time` or `Value ~ Time | Series`. See the `facet` argument +#' description for more details and the examples for some illustrations. +#' +#' @param x an object of class `"ts"`. +#' @param facet specification of `facet` for `tinyplot.formula`. The +#' default in the `tinyplot` method is to use `facet = NULL` for univariate +#' series and `facet = ~ Series` (equivalent to `facet = "by"`) for multivariate series. +#' @param type,facet.args,ylab,... further arguments passed to `tinyplot`. +#' +#' @examples +#' tinytheme("clean2") +#' +#' ## univariate series +#' tinyplot(Nile) +#' +#' ## multivariate +#' tinyplot(EuStockMarkets) ## multiple, same color, free scales +#' tinyplot(EuStockMarkets, facet.args = NULL) ## multiple, same color, same scale +#' tinyplot(EuStockMarkets, facet = "by") ## multiple, separate colors, free scales +#' tinyplot(EuStockMarkets, facet = NULL) ## single, separate colors +#' +#' ## further variations +#' tinyplot(EuStockMarkets, facet = "by", facet.args = NULL) +#' tinyplot(EuStockMarkets, facet.args = list(free = TRUE, ncol = 1)) +#' +#' tinytheme() ## reset +#' +#' @export +tinyplot.ts = function(x, facet, type = "l", facet.args = list(free = TRUE), ylab = "", ...) { + ## basic object properties + n = NROW(x) + k = NCOL(x) + lab = deparse(substitute(x)) + if (k > 1L) lab = paste(lab, 1L:k, sep = ".") + if (!is.null(colnames(x))) lab = colnames(x) + + ## convert to long data.frame + df = data.frame( + Time = rep.int(as.numeric(time(x)), k), + Value = as.numeric(x), + Series = factor(rep(1L:k, each = n), labels = lab) + ) + + ## default for facet + single = k == 1L + if(missing(facet)) { + auto = TRUE + facet = if(single) NULL else ~ Series + } else { + auto = FALSE + } + if (is.null(facet)) facet.args = NULL + + ## call tinyplot + if(single | (!is.null(facet) & auto)) { + tinyplot(Value ~ Time, data = df, facet = facet, facet.args = facet.args, type = type, ylab = ylab, ...) + } else { + tinyplot(Value ~ Time | Series, data = df, facet = facet, facet.args = facet.args, type = type, ylab = ylab, ...) + } +} From e02feb4475e45591f4547568ac8023a598d95b4c Mon Sep 17 00:00:00 2001 From: Achim Zeileis Date: Sun, 22 Mar 2026 12:35:46 +0100 Subject: [PATCH 2/5] add documentation --- NAMESPACE | 1 + man/tinyplot.ts.Rd | 48 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 man/tinyplot.ts.Rd diff --git a/NAMESPACE b/NAMESPACE index 30d3736e..486ba883 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -3,6 +3,7 @@ S3method(tinyplot,default) S3method(tinyplot,density) S3method(tinyplot,formula) +S3method(tinyplot,ts) export(draw_legend) export(get_saved_par) export(plt) diff --git a/man/tinyplot.ts.Rd b/man/tinyplot.ts.Rd new file mode 100644 index 00000000..752897f8 --- /dev/null +++ b/man/tinyplot.ts.Rd @@ -0,0 +1,48 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/tinyplot.ts.R +\name{tinyplot.ts} +\alias{tinyplot.ts} +\title{tinyplot Method for Plotting ts Objects (Time Series)} +\usage{ +\method{tinyplot}{ts}(x, facet, type = "l", facet.args = list(free = TRUE), ylab = "", ...) +} +\arguments{ +\item{x}{an object of class \code{"ts"}.} + +\item{facet}{specification of \code{facet} for \code{tinyplot.formula}. The +default in the \code{tinyplot} method is to use \code{facet = NULL} for univariate +series and \code{facet = ~ Series} (equivalent to \code{facet = "by"}) for multivariate series.} + +\item{type, facet.args, ylab, ...}{further arguments passed to \code{tinyplot}.} +} +\description{ +Convenience interface for visualizing ts objects +(time sereis with tinyplot. +} +\details{ +Internally the time series object is converted to a long +data frame with columns \code{Time} (time index), \code{Value} (observations), +and \code{Series} (factor with column labels). Depending on the settings +of \code{facet} this data frame is visualized either with the formula +\code{Value ~ Time} or \code{Value ~ Time | Series}. See the \code{facet} argument +description for more details and the examples for some illustrations. +} +\examples{ +tinytheme("clean2") + +## univariate series +tinyplot(Nile) + +## multivariate +tinyplot(EuStockMarkets) ## multiple, same color, free scales +tinyplot(EuStockMarkets, facet.args = NULL) ## multiple, same color, same scale +tinyplot(EuStockMarkets, facet = "by") ## multiple, separate colors, free scales +tinyplot(EuStockMarkets, facet = NULL) ## single, separate colors + +## further variations +tinyplot(EuStockMarkets, facet = "by", facet.args = NULL) +tinyplot(EuStockMarkets, facet.args = list(free = TRUE, ncol = 1)) + +tinytheme() ## reset + +} From e83ca71b88c58b8473012172c4c2dc213f24808f Mon Sep 17 00:00:00 2001 From: Achim Zeileis Date: Sun, 22 Mar 2026 17:48:28 +0100 Subject: [PATCH 3/5] import time() extractor --- NAMESPACE | 1 + R/tinyplot.ts.R | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 486ba883..f65fd458 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -123,6 +123,7 @@ importFrom(stats,quantile) importFrom(stats,setNames) importFrom(stats,spline) importFrom(stats,terms) +importFrom(stats,time) importFrom(stats,weighted.mean) importFrom(tools,file_ext) importFrom(utils,globalVariables) diff --git a/R/tinyplot.ts.R b/R/tinyplot.ts.R index 82625b9f..7576049a 100644 --- a/R/tinyplot.ts.R +++ b/R/tinyplot.ts.R @@ -27,13 +27,14 @@ #' tinyplot(EuStockMarkets, facet.args = NULL) ## multiple, same color, same scale #' tinyplot(EuStockMarkets, facet = "by") ## multiple, separate colors, free scales #' tinyplot(EuStockMarkets, facet = NULL) ## single, separate colors -#' +#' #' ## further variations #' tinyplot(EuStockMarkets, facet = "by", facet.args = NULL) #' tinyplot(EuStockMarkets, facet.args = list(free = TRUE, ncol = 1)) -#' +#' #' tinytheme() ## reset -#' +#' +#' @importFrom stats time #' @export tinyplot.ts = function(x, facet, type = "l", facet.args = list(free = TRUE), ylab = "", ...) { ## basic object properties From 4fd44ec2d6e346291a6e7e12c121e352d5cb4642 Mon Sep 17 00:00:00 2001 From: Achim Zeileis Date: Sun, 22 Mar 2026 17:52:35 +0100 Subject: [PATCH 4/5] tests for tinyplot.ts --- .../_tinysnapshot/ts-multivariate-by-free.svg | 260 ++++++++++++++++++ .../_tinysnapshot/ts-multivariate-by-same.svg | 242 ++++++++++++++++ .../_tinysnapshot/ts-multivariate-column.svg | 228 +++++++++++++++ .../_tinysnapshot/ts-multivariate-free.svg | 242 ++++++++++++++++ .../_tinysnapshot/ts-multivariate-same.svg | 224 +++++++++++++++ .../_tinysnapshot/ts-multivariate-single.svg | 87 ++++++ inst/tinytest/_tinysnapshot/ts-univariate.svg | 65 +++++ inst/tinytest/test-ts.R | 48 ++++ 8 files changed, 1396 insertions(+) create mode 100644 inst/tinytest/_tinysnapshot/ts-multivariate-by-free.svg create mode 100644 inst/tinytest/_tinysnapshot/ts-multivariate-by-same.svg create mode 100644 inst/tinytest/_tinysnapshot/ts-multivariate-column.svg create mode 100644 inst/tinytest/_tinysnapshot/ts-multivariate-free.svg create mode 100644 inst/tinytest/_tinysnapshot/ts-multivariate-same.svg create mode 100644 inst/tinytest/_tinysnapshot/ts-multivariate-single.svg create mode 100644 inst/tinytest/_tinysnapshot/ts-univariate.svg create mode 100644 inst/tinytest/test-ts.R diff --git a/inst/tinytest/_tinysnapshot/ts-multivariate-by-free.svg b/inst/tinytest/_tinysnapshot/ts-multivariate-by-free.svg new file mode 100644 index 00000000..7f761062 --- /dev/null +++ b/inst/tinytest/_tinysnapshot/ts-multivariate-by-free.svg @@ -0,0 +1,260 @@ + + + + + + + + + + + + + + + + + + +Series +Series 1 +Series 2 +Series 3 +Series 4 +Series 5 + + + + + + + +Time + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + +-4 +-2 +0 +2 +4 + +Series 1 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + + +-10 +-8 +-6 +-4 +-2 +0 + +Series 2 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + + +-2 +0 +2 +4 +6 +8 + +Series 3 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + +-4 +-2 +0 +2 +4 + +Series 4 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + + + +-6 +-4 +-2 +0 +2 +4 +6 + +Series 5 + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inst/tinytest/_tinysnapshot/ts-multivariate-by-same.svg b/inst/tinytest/_tinysnapshot/ts-multivariate-by-same.svg new file mode 100644 index 00000000..25240471 --- /dev/null +++ b/inst/tinytest/_tinysnapshot/ts-multivariate-by-same.svg @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + +Series +Series 1 +Series 2 +Series 3 +Series 4 +Series 5 + + + + + + + +Time + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + +-10 +-5 +0 +5 + +Series 1 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + +-10 +-5 +0 +5 + +Series 2 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + +-10 +-5 +0 +5 + +Series 3 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + +-10 +-5 +0 +5 + +Series 4 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + +-10 +-5 +0 +5 + +Series 5 + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inst/tinytest/_tinysnapshot/ts-multivariate-column.svg b/inst/tinytest/_tinysnapshot/ts-multivariate-column.svg new file mode 100644 index 00000000..87b988f3 --- /dev/null +++ b/inst/tinytest/_tinysnapshot/ts-multivariate-column.svg @@ -0,0 +1,228 @@ + + + + + + + + + + + + + +Time + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + +-4 +0 +4 + +Series 1 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + + +-10 +-4 +0 + +Series 2 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + + +-2 +2 +6 + +Series 3 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + +-4 +0 +4 + +Series 4 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + + + +-6 +0 +4 + +Series 5 + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inst/tinytest/_tinysnapshot/ts-multivariate-free.svg b/inst/tinytest/_tinysnapshot/ts-multivariate-free.svg new file mode 100644 index 00000000..88b7b622 --- /dev/null +++ b/inst/tinytest/_tinysnapshot/ts-multivariate-free.svg @@ -0,0 +1,242 @@ + + + + + + + + + + + + + +Time + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + +-4 +-2 +0 +2 +4 + +Series 1 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + + +-10 +-8 +-6 +-4 +-2 +0 + +Series 2 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + + +-2 +0 +2 +4 +6 +8 + +Series 3 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + +-4 +-2 +0 +2 +4 + +Series 4 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + + + +-6 +-4 +-2 +0 +2 +4 +6 + +Series 5 + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inst/tinytest/_tinysnapshot/ts-multivariate-same.svg b/inst/tinytest/_tinysnapshot/ts-multivariate-same.svg new file mode 100644 index 00000000..b70592c3 --- /dev/null +++ b/inst/tinytest/_tinysnapshot/ts-multivariate-same.svg @@ -0,0 +1,224 @@ + + + + + + + + + + + + + +Time + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + +-10 +-5 +0 +5 + +Series 1 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + +-10 +-5 +0 +5 + +Series 2 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + +-10 +-5 +0 +5 + +Series 3 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + +-10 +-5 +0 +5 + +Series 4 + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + +-10 +-5 +0 +5 + +Series 5 + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inst/tinytest/_tinysnapshot/ts-multivariate-single.svg b/inst/tinytest/_tinysnapshot/ts-multivariate-single.svg new file mode 100644 index 00000000..6bc4d24c --- /dev/null +++ b/inst/tinytest/_tinysnapshot/ts-multivariate-single.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + +Series +Series 1 +Series 2 +Series 3 +Series 4 +Series 5 + + + + + + + +Time + + + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + +-10 +-5 +0 +5 + + + + + + + + + + + + + + + + diff --git a/inst/tinytest/_tinysnapshot/ts-univariate.svg b/inst/tinytest/_tinysnapshot/ts-univariate.svg new file mode 100644 index 00000000..1266463e --- /dev/null +++ b/inst/tinytest/_tinysnapshot/ts-univariate.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + +Time + + + + + + + +0 +20 +40 +60 +80 +100 + + + + + + +-4 +-2 +0 +2 +4 + + + + + + + + + + + + diff --git a/inst/tinytest/test-ts.R b/inst/tinytest/test-ts.R new file mode 100644 index 00000000..39943745 --- /dev/null +++ b/inst/tinytest/test-ts.R @@ -0,0 +1,48 @@ +source("helpers.R") +using("tinysnapshot") + +## five random walks +set.seed(0) +x = c(0, rnorm(100)) |> + cumsum() |> + replicate(n = 5) |> + ts(start = 0) + +## univariate + +f = function() { + tinyplot(x[, 1]) +} +expect_snapshot_plot(f, label = "ts-univariate") + +## multivariate + +f = function() { + tinyplot(x) +} +expect_snapshot_plot(f, label = "ts-multivariate-free") + +f = function() { + tinyplot(x, facet.args = NULL) +} +expect_snapshot_plot(f, label = "ts-multivariate-same") + +f = function() { + tinyplot(x, facet = "by") +} +expect_snapshot_plot(f, label = "ts-multivariate-by-free") + +f = function() { + tinyplot(x, facet = "by", facet.args = NULL) +} +expect_snapshot_plot(f, label = "ts-multivariate-by-same") + +f = function() { + tinyplot(x, facet = NULL) +} +expect_snapshot_plot(f, label = "ts-multivariate-single") + +f = function() { + tinyplot(x, facet.args = list(free = TRUE, ncol = 1)) +} +expect_snapshot_plot(f, label = "ts-multivariate-column") From fe908c219c0a7e1c01e25523840be7b82b622a48 Mon Sep 17 00:00:00 2001 From: Achim Zeileis Date: Sun, 22 Mar 2026 17:56:19 +0100 Subject: [PATCH 5/5] NEWS item for tinyplot.ts --- NEWS.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS.md b/NEWS.md index 49a7d229..c173597c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,6 +6,13 @@ where the formatting is also better._ ## Development version +### New features + +- New dedicated `tinyplot()` method for `ts` time series. Internally, this sets + up a long data frame with columns `Time`, `Value`, and `Series` and then calls + the formula method with different possible specifications for the `by` and `facet` + variables. (#558 @zeileis) + ### Aesthetic changes - The legend plot characters for the `"pointrange"` and `"errorbar"` types now