From 54478c46c1d7c645f1899a885656393a143a857c Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Sat, 27 Sep 2025 14:06:20 -0700 Subject: [PATCH 1/6] support family arg --- R/type_text.R | 27 ++++++++++++++++++--------- man/type_text.Rd | 16 ++++++++++++---- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/R/type_text.R b/R/type_text.R index dca76325..6a0ec55a 100644 --- a/R/type_text.R +++ b/R/type_text.R @@ -1,13 +1,19 @@ #' Text annotations plot type #' -#' @description Type function for adding text annotations to a plot. This function allows -#' you to draw text at specified (x,y) coordinates. -#' +#' @description Type function for adding text annotations to a plot at the +#' specified (`x`,`y`) coordinates. +#' #' @param labels Character vector of length 1 or of the same length as the #' number of x,y coordinates. -#' @param font Font to be used, following [graphics::par()]. +#' @param family The name of a font family. Default of `NULL` means that the +#' family will be the same as the main plot text, following +#' \code{\link[graphics]{par}}. Note that if a `family` argument is provided, +#' then `vfont` (below) will automatically be ignored. +#' @param font Integer giving the font face to be used, +#' following \code{\link[graphics]{par}}. On most devices, the mapping is: `1` = +#' regular, `2` = bold, `3` = italic, `4` = bold italic, and `5` = symbol. #' @param xpd Logical value or `NA` denoting text clipping behaviour, following -#' [graphics::par()]. +#' \code{\link[graphics]{par}}. #' @param srt Numeric giving the desired string rotation in degrees. #' @param clim Numeric giving the lower and upper limits of the character #' expansion (`cex`) normalization for bubble charts. @@ -34,9 +40,9 @@ #' ) #' #' @export -type_text = function(labels, adj = NULL, pos = NULL, offset = 0.5, vfont = NULL, font = NULL, xpd = NULL, srt = 0, clim = c(0.5, 2.5)) { +type_text = function(labels, adj = NULL, pos = NULL, offset = 0.5, family = NULL, font = NULL, vfont = NULL, xpd = NULL, srt = 0, clim = c(0.5, 2.5)) { out = list( - draw = draw_text(adj = adj, pos = pos, offset = offset, vfont = vfont, font = font, xpd = xpd, srt = srt), + draw = draw_text(adj = adj, pos = pos, offset = offset, vfont = vfont, family = family, font = font, xpd = xpd, srt = srt), data = data_text(labels = labels, clim = clim), name = "text" ) @@ -89,13 +95,16 @@ data_text = function(labels, clim = c(0.5, 2.5)) { return(fun) } -draw_text = function(adj = NULL, pos = NULL, offset = 0.5, vfont = NULL, font = NULL, xpd = NULL, srt = 0) { +draw_text = function(adj = NULL, pos = NULL, offset = 0.5, vfont = NULL, family = NULL, font = NULL, xpd = NULL, srt = 0) { if (is.null(xpd)) xpd = par("xpd") + if (!is.null(family)) vfont = NULL fun = function(ix, iy, ilabels, icol, icex, ...) { text( x = ix, y = iy, labels = ilabels, col = icol, adj = adj, pos = pos, offset = offset, - vfont = vfont, font = font, + family = family, + font = font, + vfont = vfont, xpd = xpd, srt = srt, cex = icex diff --git a/man/type_text.Rd b/man/type_text.Rd index 8b930e26..8bdabddb 100644 --- a/man/type_text.Rd +++ b/man/type_text.Rd @@ -10,6 +10,7 @@ type_text( pos = NULL, offset = 0.5, vfont = NULL, + family = NULL, font = NULL, xpd = NULL, srt = 0, @@ -42,10 +43,17 @@ number of x,y coordinates.} the vector selects a typeface and the second element selects a style. Ignored if \code{labels} is an expression.} -\item{font}{Font to be used, following \code{\link[graphics:par]{graphics::par()}}.} +\item{family}{The name of a font family. Default of \code{NULL} means that the +family will be the same as the main plot text, following +\code{\link[graphics]{par}}. Note that if a \code{family} argument is provided, +then \code{vfont} (below) will automatically be ignored.} + +\item{font}{Integer giving the font face to be used, +following \code{\link[graphics]{par}}. On most devices, the mapping is: \code{1} = +regular, \code{2} = bold, \code{3} = italic, \code{4} = bold italic, and \code{5} = symbol.} \item{xpd}{Logical value or \code{NA} denoting text clipping behaviour, following -\code{\link[graphics:par]{graphics::par()}}.} +\code{\link[graphics]{par}}.} \item{srt}{Numeric giving the desired string rotation in degrees.} @@ -53,8 +61,8 @@ number of x,y coordinates.} expansion (\code{cex}) normalization for bubble charts.} } \description{ -Type function for adding text annotations to a plot. This function allows -you to draw text at specified (x,y) coordinates. +Type function for adding text annotations to a plot at the +specified (\code{x},\code{y}) coordinates. } \examples{ tinyplot(mpg ~ hp | factor(cyl), From 49ad60f2218d51646e444ca6558829df79ea538d Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Sat, 27 Sep 2025 14:20:23 -0700 Subject: [PATCH 2/6] auto-inherit y values if labels NULL --- R/type_text.R | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/R/type_text.R b/R/type_text.R index 6a0ec55a..c5b99595 100644 --- a/R/type_text.R +++ b/R/type_text.R @@ -3,8 +3,9 @@ #' @description Type function for adding text annotations to a plot at the #' specified (`x`,`y`) coordinates. #' -#' @param labels Character vector of length 1 or of the same length as the -#' number of x,y coordinates. +#' @param labels Character vector of length `1` or the same length as the +#' number of `x`,`y` coordinates. If left as `NULL`, then the labels will +#' automatically inherit the corresponding `y` values. #' @param family The name of a font family. Default of `NULL` means that the #' family will be the same as the main plot text, following #' \code{\link[graphics]{par}}. Note that if a `family` argument is provided, @@ -40,7 +41,7 @@ #' ) #' #' @export -type_text = function(labels, adj = NULL, pos = NULL, offset = 0.5, family = NULL, font = NULL, vfont = NULL, xpd = NULL, srt = 0, clim = c(0.5, 2.5)) { +type_text = function(labels = NULL, adj = NULL, pos = NULL, offset = 0.5, family = NULL, font = NULL, vfont = NULL, xpd = NULL, srt = 0, clim = c(0.5, 2.5)) { out = list( draw = draw_text(adj = adj, pos = pos, offset = offset, vfont = vfont, family = family, font = font, xpd = xpd, srt = srt), data = data_text(labels = labels, clim = clim), @@ -50,8 +51,9 @@ type_text = function(labels, adj = NULL, pos = NULL, offset = 0.5, family = NULL return(out) } -data_text = function(labels, clim = c(0.5, 2.5)) { +data_text = function(labels = NULL, clim = c(0.5, 2.5)) { fun = function(datapoints, legend_args, cex = NULL, ...) { + if (is.null(labels)) labels = datapoints$y if (length(labels) != 1 && length(labels) != nrow(datapoints)) { msg = sprintf("`labels` must be of length 1 or %s.", nrow(datapoints)) stop(msg, call. = FALSE) @@ -60,7 +62,6 @@ data_text = function(labels, clim = c(0.5, 2.5)) { if (is.factor(datapoints$x)) datapoints$x = as.numeric(datapoints$x) if (is.factor(datapoints$y)) datapoints$y = as.numeric(datapoints$y) - # browser() bubble = FALSE bubble_cex = 1 if (!is.null(cex) && length(cex) == nrow(datapoints)) { From 40ae07a160ee6fb2df450662ce0daf68a7f9d3f3 Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Sat, 27 Sep 2025 14:35:25 -0700 Subject: [PATCH 3/6] document --- R/type_text.R | 17 +++++++++++++++-- man/type_text.Rd | 36 +++++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/R/type_text.R b/R/type_text.R index c5b99595..f84b3e02 100644 --- a/R/type_text.R +++ b/R/type_text.R @@ -5,7 +5,7 @@ #' #' @param labels Character vector of length `1` or the same length as the #' number of `x`,`y` coordinates. If left as `NULL`, then the labels will -#' automatically inherit the corresponding `y` values. +#' automatically inherit the corresponding `y` values. See Examples. #' @param family The name of a font family. Default of `NULL` means that the #' family will be the same as the main plot text, following #' \code{\link[graphics]{par}}. Note that if a `family` argument is provided, @@ -20,20 +20,33 @@ #' expansion (`cex`) normalization for bubble charts. #' @inheritParams graphics::text #' @examples +#' # simplest case (no labels), will auto revert to y labels +#' tinyplot(1:12, type = "text") +#' +#' # pass explicit `labels` arg if you want specific text +#' tinyplot(1:12, type = "text", labels = month.abb) +#' +#' # for advanced customization, it's safer to pass args through `type_text()` +#' tinyplot(1:12, type = type_text( +#' labels = month.abb, family = "HersheyScript", srt = -20)) +#' +#' # same principles apply to grouped and/or facet data #' tinyplot(mpg ~ hp | factor(cyl), #' data = mtcars, #' type = type_text( #' labels = row.names(mtcars), +#' family = "HersheySans", #' font = 2, #' adj = 0 #' ) #' ) #' -#' # to avoid clipping text at the plot region, we can use xpd = NA +#' # tip: use `xpd = NA` to avoid clipping text at the plot region #' tinyplot(mpg ~ hp | factor(cyl), #' data = mtcars, #' type = type_text( #' labels = row.names(mtcars), +#' family = "HersheySans", #' font = 2, #' adj = 0, #' xpd = NA diff --git a/man/type_text.Rd b/man/type_text.Rd index 8bdabddb..03879c98 100644 --- a/man/type_text.Rd +++ b/man/type_text.Rd @@ -5,21 +5,22 @@ \title{Text annotations plot type} \usage{ type_text( - labels, + labels = NULL, adj = NULL, pos = NULL, offset = 0.5, - vfont = NULL, family = NULL, font = NULL, + vfont = NULL, xpd = NULL, srt = 0, clim = c(0.5, 2.5) ) } \arguments{ -\item{labels}{Character vector of length 1 or of the same length as the -number of x,y coordinates.} +\item{labels}{Character vector of length \code{1} or the same length as the +number of \code{x},\code{y} coordinates. If left as \code{NULL}, then the labels will +automatically inherit the corresponding \code{y} values. See Examples.} \item{adj}{one or two values in \eqn{[0, 1]} which specify the x (and optionally y) adjustment (\sQuote{justification}) of the @@ -37,12 +38,6 @@ number of x,y coordinates.} distance (\sQuote{offset}) of the text label from the specified coordinate in fractions of a character width.} -\item{vfont}{\code{NULL} for the current font family, or a character - vector of length 2 for \code{\link[grDevices]{Hershey}} vector - fonts. The first element of - the vector selects a typeface and the second element selects a - style. Ignored if \code{labels} is an expression.} - \item{family}{The name of a font family. Default of \code{NULL} means that the family will be the same as the main plot text, following \code{\link[graphics]{par}}. Note that if a \code{family} argument is provided, @@ -52,6 +47,12 @@ then \code{vfont} (below) will automatically be ignored.} following \code{\link[graphics]{par}}. On most devices, the mapping is: \code{1} = regular, \code{2} = bold, \code{3} = italic, \code{4} = bold italic, and \code{5} = symbol.} +\item{vfont}{\code{NULL} for the current font family, or a character + vector of length 2 for \code{\link[grDevices]{Hershey}} vector + fonts. The first element of + the vector selects a typeface and the second element selects a + style. Ignored if \code{labels} is an expression.} + \item{xpd}{Logical value or \code{NA} denoting text clipping behaviour, following \code{\link[graphics]{par}}.} @@ -65,20 +66,33 @@ Type function for adding text annotations to a plot at the specified (\code{x},\code{y}) coordinates. } \examples{ +# simplest case (no labels), will auto revert to y labels +tinyplot(1:12, type = "text") + +# pass explicit `labels` arg if you want specific text +tinyplot(1:12, type = "text", labels = month.abb) + +# for advanced customization, it's safer to pass args through `type_text()` +tinyplot(1:12, type = type_text( + labels = month.abb, family = "HersheyScript", srt = -20)) + +# same principles apply to grouped and/or facet data tinyplot(mpg ~ hp | factor(cyl), data = mtcars, type = type_text( labels = row.names(mtcars), + family = "HersheySans", font = 2, adj = 0 ) ) -# to avoid clipping text at the plot region, we can use xpd = NA +# tip: use `xpd = NA` to avoid clipping text at the plot region tinyplot(mpg ~ hp | factor(cyl), data = mtcars, type = type_text( labels = row.names(mtcars), + family = "HersheySans", font = 2, adj = 0, xpd = NA From a7233063a640f11e904922ff0d7182c7f05d30f5 Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Sat, 27 Sep 2025 14:43:30 -0700 Subject: [PATCH 4/6] news --- NEWS.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/NEWS.md b/NEWS.md index 17b02e75..118e5db6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,12 +6,20 @@ where the formatting is also better._ ## Dev version +### New features + +- `type_text()` gains a `family` argument for (separately) controlling the font + family versus to the main plot text elements. (#494 @grantmcdermott) + ### Bug fixes - For bubble plots, we now drop the minimum legend category (label) if it is equal to 0. The previous behaviour was just an artifact of the `pretty` breaks algorithm that we use to create discrete legend categories. The interior plot elements, e.g. bubble points, are unaffected. (#498 @grantmcdermott) +- `type_text()` now defaults to displaying `y` values if an explicit `label` arg + is not provided, mirroring the behaviour of the base `text()` function. + (#501 @grantmcdermott) ## 0.5.0 From 624c7b923e1c782ee2cd7dc395e81ca1e47fe198 Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Sat, 27 Sep 2025 14:45:49 -0700 Subject: [PATCH 5/6] formatting --- R/type_text.R | 72 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/R/type_text.R b/R/type_text.R index f84b3e02..90ca2819 100644 --- a/R/type_text.R +++ b/R/type_text.R @@ -2,7 +2,7 @@ #' #' @description Type function for adding text annotations to a plot at the #' specified (`x`,`y`) coordinates. -#' +#' #' @param labels Character vector of length `1` or the same length as the #' number of `x`,`y` coordinates. If left as `NULL`, then the labels will #' automatically inherit the corresponding `y` values. See Examples. @@ -22,14 +22,14 @@ #' @examples #' # simplest case (no labels), will auto revert to y labels #' tinyplot(1:12, type = "text") -#' +#' #' # pass explicit `labels` arg if you want specific text #' tinyplot(1:12, type = "text", labels = month.abb) -#' +#' #' # for advanced customization, it's safer to pass args through `type_text()` #' tinyplot(1:12, type = type_text( #' labels = month.abb, family = "HersheyScript", srt = -20)) -#' +#' #' # same principles apply to grouped and/or facet data #' tinyplot(mpg ~ hp | factor(cyl), #' data = mtcars, @@ -54,9 +54,29 @@ #' ) #' #' @export -type_text = function(labels = NULL, adj = NULL, pos = NULL, offset = 0.5, family = NULL, font = NULL, vfont = NULL, xpd = NULL, srt = 0, clim = c(0.5, 2.5)) { +type_text = function( + labels = NULL, + adj = NULL, + pos = NULL, + offset = 0.5, + family = NULL, + font = NULL, + vfont = NULL, + xpd = NULL, + srt = 0, + clim = c(0.5, 2.5) +) { out = list( - draw = draw_text(adj = adj, pos = pos, offset = offset, vfont = vfont, family = family, font = font, xpd = xpd, srt = srt), + draw = draw_text( + adj = adj, + pos = pos, + offset = offset, + vfont = vfont, + family = family, + font = font, + xpd = xpd, + srt = srt + ), data = data_text(labels = labels, clim = clim), name = "text" ) @@ -66,14 +86,20 @@ type_text = function(labels = NULL, adj = NULL, pos = NULL, offset = 0.5, family data_text = function(labels = NULL, clim = c(0.5, 2.5)) { fun = function(datapoints, legend_args, cex = NULL, ...) { - if (is.null(labels)) labels = datapoints$y + if (is.null(labels)) { + labels = datapoints$y + } if (length(labels) != 1 && length(labels) != nrow(datapoints)) { msg = sprintf("`labels` must be of length 1 or %s.", nrow(datapoints)) stop(msg, call. = FALSE) } datapoints$labels = labels - if (is.factor(datapoints$x)) datapoints$x = as.numeric(datapoints$x) - if (is.factor(datapoints$y)) datapoints$y = as.numeric(datapoints$y) + if (is.factor(datapoints$x)) { + datapoints$x = as.numeric(datapoints$x) + } + if (is.factor(datapoints$y)) { + datapoints$y = as.numeric(datapoints$y) + } bubble = FALSE bubble_cex = 1 @@ -109,13 +135,31 @@ data_text = function(labels = NULL, clim = c(0.5, 2.5)) { return(fun) } -draw_text = function(adj = NULL, pos = NULL, offset = 0.5, vfont = NULL, family = NULL, font = NULL, xpd = NULL, srt = 0) { - if (is.null(xpd)) xpd = par("xpd") - if (!is.null(family)) vfont = NULL +draw_text = function( + adj = NULL, + pos = NULL, + offset = 0.5, + vfont = NULL, + family = NULL, + font = NULL, + xpd = NULL, + srt = 0 +) { + if (is.null(xpd)) { + xpd = par("xpd") + } + if (!is.null(family)) { + vfont = NULL + } fun = function(ix, iy, ilabels, icol, icex, ...) { text( - x = ix, y = iy, labels = ilabels, col = icol, - adj = adj, pos = pos, offset = offset, + x = ix, + y = iy, + labels = ilabels, + col = icol, + adj = adj, + pos = pos, + offset = offset, family = family, font = font, vfont = vfont, From e090f42fc63bff3eccc7c410e1c2daba83de0dc1 Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Sat, 27 Sep 2025 14:56:06 -0700 Subject: [PATCH 6/6] typos --- NEWS.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/NEWS.md b/NEWS.md index 118e5db6..110102eb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -8,8 +8,8 @@ where the formatting is also better._ ### New features -- `type_text()` gains a `family` argument for (separately) controlling the font - family versus to the main plot text elements. (#494 @grantmcdermott) +- `type_text()` gains a `family` argument for controlling the font family, + separate to the main plot text elements. (#494 @grantmcdermott) ### Bug fixes @@ -17,8 +17,8 @@ where the formatting is also better._ equal to 0. The previous behaviour was just an artifact of the `pretty` breaks algorithm that we use to create discrete legend categories. The interior plot elements, e.g. bubble points, are unaffected. (#498 @grantmcdermott) -- `type_text()` now defaults to displaying `y` values if an explicit `label` arg - is not provided, mirroring the behaviour of the base `text()` function. +- `type_text()` now defaults to displaying `y` values if an explicit `labels` + arg is not provided, mirroring the behaviour of the base `text()` function. (#501 @grantmcdermott) ## 0.5.0