diff --git a/NAMESPACE b/NAMESPACE
index 01a84fde..71757a03 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -70,6 +70,7 @@ importFrom(grDevices,xy.coords)
importFrom(graphics,Axis)
importFrom(graphics,abline)
importFrom(graphics,arrows)
+importFrom(graphics,axTicks)
importFrom(graphics,axis)
importFrom(graphics,box)
importFrom(graphics,boxplot)
diff --git a/NEWS.md b/NEWS.md
index 53267229..55fcde4c 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -23,6 +23,10 @@ where the formatting is also better._
- The palette argument now accepts a vector or list of manual colours, e.g.
`tinyplot(..., palette = c("cyan4", "hotpink, "purple4"))`, or
`tinytheme("clean", palette = c("cyan4", "hotpink, "purple4"))` (#325 @grantmcdermott)
+- The new top-level `xaxl` and `yaxl` arguments allow users to format the
+ appearance of their axis tick labels. Several convenience strings are
+ supported for common cases, e.g., `tinyplot(..., xaxl = "percent")` or
+ `tinyplot(..., yaxl = "dollar")`, etc. (#363 @grantmcdermott)
### Bugs fixes:
diff --git a/R/facet.R b/R/facet.R
index e7b4e6ac..29634a01 100644
--- a/R/facet.R
+++ b/R/facet.R
@@ -181,18 +181,20 @@ draw_facet_window = function(grid, ...) {
if (dynmar) {
if (par("las") %in% 1:2) {
# extra whitespace bump on the y axis
- # yaxl = axTicks(2)
- yaxl = axisTicks(usr = extendrange(ylim, f = 0.04), log = par("ylog"))
## overrides for ridge and some types that use integer spacing with (named) axis labels ## FXIME
if (type == "ridge") {
- yaxl = levels(y)
+ yaxlabs = levels(y)
} else if (!is.null(ylabs)) {
- yaxl = if (!is.null(names(ylabs))) names(ylabs) else ylabs
+ yaxlabs = if (!is.null(names(ylabs))) names(ylabs) else ylabs
} else if (type == "boxplot" && isTRUE(flip) && !is.null(xlabs)) {
- yaxl = if (!is.null(names(xlabs))) names(xlabs) else xlabs
+ yaxlabs = if (!is.null(names(xlabs))) names(xlabs) else xlabs
+ } else {
+ # yaxl = axTicks(2)
+ yaxlabs = axisTicks(usr = extendrange(ylim, f = 0.04), log = par("ylog"))
}
+ if (!is.null(yaxl)) yaxlabs = tinylabel(yaxlabs, yaxl)
# whtsbp = grconvertX(max(strwidth(yaxl, "figure")), from = "nfc", to = "lines") - 1
- whtsbp = grconvertX(max(strwidth(yaxl, "figure")), from = "nfc", to = "lines") - grconvertX(0, from = "nfc", to = "lines") - 1
+ whtsbp = grconvertX(max(strwidth(yaxlabs, "figure")), from = "nfc", to = "lines") - grconvertX(0, from = "nfc", to = "lines") - 1
if (whtsbp > 0) {
omar = omar + c(0, whtsbp, 0, 0) * cex_fct_adj
fmar[2] = fmar[2] + whtsbp * cex_fct_adj
@@ -200,10 +202,11 @@ draw_facet_window = function(grid, ...) {
}
if (par("las") %in% 2:3) {
# extra whitespace bump on the x axis
- # xaxl = axTicks(1)
- xaxl = axisTicks(usr = extendrange(xlim, f = 0.04), log = par("xlog"))
- whtsbp = grconvertY(max(strwidth(xaxl, "figure")), from = "nfc", to = "lines") - 1
- # whtsbp = grconvertY(max(strwidth(xaxl, "figure")), from = "nfc", to = "lines") - grconvertY(0, from = "nfc", to = "lines") - 1
+ # xaxlabs = axTicks(1)
+ xaxlabs = axisTicks(usr = extendrange(xlim, f = 0.04), log = par("xlog"))
+ if (!is.null(xaxl)) xaxlabs = tinylabel(xaxlabs, xaxl)
+ whtsbp = grconvertY(max(strwidth(xaxlabs, "figure")), from = "nfc", to = "lines") - 1
+ # whtsbp = grconvertY(max(strwidth(xaxlabs, "figure")), from = "nfc", to = "lines") - grconvertY(0, from = "nfc", to = "lines") - 1
if (whtsbp > 0) {
omar = omar + c(whtsbp, 0, 0, 0) * cex_fct_adj
fmar[1] = fmar[1] + whtsbp * cex_fct_adj
@@ -247,18 +250,20 @@ draw_facet_window = function(grid, ...) {
if (type == "spineplot") omar[4] = 2.1 # FIXME catch for spineplot RHS axis labs
if (par("las") %in% 1:2) {
# extra whitespace bump on the y axis
- # yaxl = axTicks(2)
- yaxl = axisTicks(usr = extendrange(ylim, f = 0.04), log = par("ylog"))
## overrides for ridge and some types that use integer spacing with (named) axis labels ## FXIME
if (type == "ridge") {
- yaxl = levels(y)
+ yaxlabs = levels(y)
} else if (!is.null(ylabs)) {
- yaxl = if (!is.null(names(ylabs))) names(ylabs) else ylabs
+ yaxlabs = if (!is.null(names(ylabs))) names(ylabs) else ylabs
} else if (type == "boxplot" && isTRUE(flip) && !is.null(xlabs)) {
- yaxl = if (!is.null(names(xlabs))) names(xlabs) else xlabs
+ yaxlabs = if (!is.null(names(xlabs))) names(xlabs) else xlabs
+ } else {
+ # yaxl = axTicks(2)
+ yaxlabs = axisTicks(usr = extendrange(ylim, f = 0.04), log = par("ylog"))
}
- # whtsbp = grconvertX(max(strwidth(yaxl, "figure")), from = "nfc", to = "lines") - 1
- whtsbp = grconvertX(max(strwidth(yaxl, "figure")), from = "nfc", to = "lines") - grconvertX(0, from = "nfc", to = "lines") - 1
+ if (!is.null(yaxl)) yaxlabs = tinylabel(yaxlabs, yaxl)
+ # whtsbp = grconvertX(max(strwidth(yaxlabs, "figure")), from = "nfc", to = "lines") - 1
+ whtsbp = grconvertX(max(strwidth(yaxlabs, "figure")), from = "nfc", to = "lines") - grconvertX(0, from = "nfc", to = "lines") - 1
if (whtsbp > 0) {
omar[2] = omar[2] + whtsbp
}
@@ -266,9 +271,10 @@ draw_facet_window = function(grid, ...) {
if (par("las") %in% 2:3) {
# extra whitespace bump on the x axis
# xaxl = axTicks(1)
- xaxl = axisTicks(usr = extendrange(ylim, f = 0.04), log = par("xlog"))
- whtsbp = grconvertY(max(strwidth(xaxl, "figure")), from = "nfc", to = "lines") - 1
- # whtsbp = grconvertY(max(strwidth(xaxl, "figure")), from = "nfc", to = "lines") - grconvertY(0, from = "nfc", to = "lines") - 1
+ xaxlabs = axisTicks(usr = extendrange(ylim, f = 0.04), log = par("xlog"))
+ if (!is.null(xaxl)) xaxlabs = tinylabel(xaxlabs, xaxl)
+ whtsbp = grconvertY(max(strwidth(xaxlabs, "figure")), from = "nfc", to = "lines") - 1
+ # whtsbp = grconvertY(max(strwidth(xaxlabs, "figure")), from = "nfc", to = "lines") - grconvertY(0, from = "nfc", to = "lines") - 1
if (whtsbp > 0) {
omar[1] = omar[1] + whtsbp
}
@@ -327,6 +333,7 @@ draw_facet_window = function(grid, ...) {
args_x = list(x,
side = xside,
type = xaxt,
+ labeller = xaxl,
cex = get_tpar(c("cex.xaxs", "cex.axis"), 0.8),
lwd = get_tpar(c("lwd.xaxs", "lwd.axis"), 1),
lty = get_tpar(c("lty.xaxs", "lty.axis"), 1)
@@ -334,6 +341,7 @@ draw_facet_window = function(grid, ...) {
args_y = list(y,
side = yside,
type = yaxt,
+ labeller = yaxl,
cex = get_tpar(c("cex.yaxs", "cex.axis"), 0.8),
lwd = get_tpar(c("lwd.yaxs", "lwd.axis"), 1),
lty = get_tpar(c("lty.yaxs", "lty.axis"), 1)
diff --git a/R/tinyAxis.R b/R/tinyAxis.R
index d7a402a9..28655231 100644
--- a/R/tinyAxis.R
+++ b/R/tinyAxis.R
@@ -1,7 +1,7 @@
#' auxiliary Axis() interface with different parameter combinations based on type
#'
#' @keywords internal
-tinyAxis = function(x = NULL, ..., type = "standard") {
+tinyAxis = function(x = NULL, ..., type = "standard", labeller = NULL) {
type = match.arg(type, c("standard", "none", "labels", "ticks", "axis"))
if (type == "none") {
invisible(numeric(0L))
@@ -17,6 +17,14 @@ tinyAxis = function(x = NULL, ..., type = "standard") {
} else {
args$tick = TRUE
}
+ if (!is.null(labeller)) {
+ if (!is.null(args$at)) {
+ args$labels = if (!is.null(args$labels)) tinylabel(args$labels, labeller) else tinylabel(args$at, labeller)
+ } else {
+ args$at = axTicks(args$side) # FIXME: log ?
+ args$labels = tinylabel(args$at, labeller)
+ }
+ }
do.call("Axis", args)
}
}
diff --git a/R/tinylabel.R b/R/tinylabel.R
new file mode 100644
index 00000000..946dcdac
--- /dev/null
+++ b/R/tinylabel.R
@@ -0,0 +1,51 @@
+#' Format labels
+#'
+#' @description Internal function for formatting label appearance, e.g. axis
+#' ticks labels. This is what the top-level `xaxl` and `yaxl` arguments
+#' ultimately get passed to.
+#' @param x a numeric or character vector
+#' @param labeller a formatting function to be applied to `x`, e.g. `abs`,
+#' `topper`, etc. Can also be one of the following convenience strings, for
+#' which common formatting transformations are provided: `"percent"`,
+#' `"comma"`, `"dollar"`, `"euro"`, or `"sterling"`.
+#'
+#' @keywords internal
+tinylabel = function(x, labeller = NULL) {
+ if (is.null(labeller)) return(x)
+ if (is.character(labeller)) labeller = labeller_fun((labeller))
+ return(labeller(x))
+}
+
+
+labeller_fun = function(label = c("percent", "comma", "dollar", "euro", "sterling")) {
+ label = match.arg(label)
+
+ format_percent = function(x) {
+ sprintf("%.0f%%", x * 100)
+ }
+
+ format_comma = function(x) {
+ prettyNum(x, big.mark = ",", scientific = FALSE)
+ }
+
+ format_dollar = function(x) {
+ paste0("$", prettyNum(x, big.mark = ",", scientific = FALSE))
+ }
+
+ format_euro = function(x) {
+ paste0("\u20ac", prettyNum(x, big.mark = ",", scientific = FALSE))
+ }
+
+ format_sterling = function(x) {
+ paste0("\u00a3", prettyNum(x, big.mark = ",", scientific = FALSE))
+ }
+
+ switch(
+ label,
+ percent = format_percent,
+ comma = format_comma,
+ dollar = format_dollar,
+ euro = format_euro,
+ sterling = format_sterling
+ )
+}
diff --git a/R/tinyplot.R b/R/tinyplot.R
index 75447fab..cbd0838f 100644
--- a/R/tinyplot.R
+++ b/R/tinyplot.R
@@ -13,6 +13,11 @@
#' 'Examples' section below, or the function
#' \code{\link[grDevices]{xy.coords}} for details. If supplied separately, `x`
#' and `y` must be of the same length.
+#' @param xmin,xmax,ymin,ymax minimum and maximum coordinates of relevant area
+#' or interval plot types. Only used when the `type` argument is one of
+#' `"rect"` or `"segments"` (where all four min-max coordinates are required),
+#' or `"pointrange"`, `"errorbar"`, or `"ribbon"` (where only `ymin` and
+#' `ymax` required alongside `x`).
#' @param by grouping variable(s). The default behaviour is for groups to be
#' represented in the form of distinct colours, which will also trigger an
#' automatic legend. (See `legend` below for customization options.) However,
@@ -126,31 +131,35 @@
#' - [`type_vline()`]: vertical line(s).
#' - [`type_function()`]: arbitrary function.
#' - [`type_summary()`]: summarize `y` by unique values of `x`.
-#' @param xmin,xmax,ymin,ymax minimum and maximum coordinates of relevant area
-#' or interval plot types. Only used when the `type` argument is one of
-#' `"rect"` or `"segments"` (where all four min-max coordinates are required),
-#' or `"pointrange"`, `"errorbar"`, or `"ribbon"` (where only `ymin` and
-#' `ymax` required alongside `x`).
-#' @param xlim the x limits (x1, x2) of the plot. Note that x1 > x2 is allowed
-#' and leads to a ‘reversed axis’. The default value, NULL, indicates that
-#' the range of the `finite` values to be plotted should be used.
-#' @param ylim the y limits of the plot.
-#' @param log a character string which contains "x" if the x axis is to be
-#' logarithmic, "y" if the y axis is to be logarithmic and "xy" or "yx" if
-#' both axes are to be logarithmic.
-#' @param empty logical indicating whether the interior plot region should be
-#' left empty. The default is `FALSE`. Setting to `TRUE` has a similar effect
-#' to invoking `type = "n"` above, except that any legend artifacts owing to a
-#' particular plot type (e.g., lines for `type = "l"` or squares for
-#' `type = "area"`) will still be drawn correctly alongside the empty plot. In
-#' contrast,`type = "n"` implicitly assumes a scatterplot and so any legend
-#' will only depict points.
+#' @param legend one of the following options:
+#' - NULL (default), in which case the legend will be determined by the
+#' grouping variable. If there is no group variable (i.e., `by` is NULL) then
+#' no legend is drawn. If a grouping variable is detected, then an automatic
+#' legend is drawn to the _outer_ right of the plotting area. Note that the
+#' legend title and categories will automatically be inferred from the `by`
+#' argument and underlying data.
+#' - A convenience string indicating the legend position. The string should
+#' correspond to one of the position keywords supported by the base `legend`
+#' function, e.g. "right", "topleft", "bottom", etc. In addition, `tinyplot`
+#' supports adding a trailing exclamation point to these keywords, e.g.
+#' "right!", "topleft!", or "bottom!". This will place the legend _outside_
+#' the plotting area and adjust the margins of the plot accordingly. Finally,
+#' users can also turn off any legend printing by specifying "none".
+#' - Logical value, where TRUE corresponds to the default case above (same
+#' effect as specifying NULL) and FALSE turns the legend off (same effect as
+#' specifying "none").
+#' - A list or, equivalently, a dedicated `legend()` function with supported
+#' legend arguments, e.g. "bty", "horiz", and so forth.
#' @param main a main title for the plot, see also `title`.
#' @param sub a subtitle for the plot.
#' @param xlab a label for the x axis, defaults to a description of x.
#' @param ylab a label for the y axis, defaults to a description of y.
#' @param ann a logical value indicating whether the default annotation (title
#' and x and y axis labels) should appear on the plot.
+#' @param xlim the x limits (x1, x2) of the plot. Note that x1 > x2 is allowed
+#' and leads to a ‘reversed axis’. The default value, NULL, indicates that
+#' the range of the `finite` values to be plotted should be used.
+#' @param ylim the y limits of the plot.
#' @param axes logical or character. Should axes be drawn (`TRUE` or `FALSE`)?
#' Or alternatively what type of axes should be drawn: `"standard"` (with
#' axis, ticks, and labels; equivalent to `TRUE`), `"none"` (no axes;
@@ -158,6 +167,22 @@
#' `"labels"` (only labels without ticks and axis line), `"axis"` (only axis
#' line and labels but no ticks). To control this separately for the two
#' axes, use the character specifications for `xaxt` and/or `yaxt`.
+#' @param xaxt,yaxt character specifying the type of x-axis and y-axis, respectively.
+#' See `axes` for the possible values.
+#' @param xaxs,yaxs character specifying the style of the interval calculation used
+#' for the x-axis and y-axis, respectively. See \code{\link[graphics]{par}}
+#' for the possible values.
+#' @param xaxl,yaxl A formatting function (or character string) to apply to the
+#' x- or y-axis tick labels. This affects the _appearance_ of the labels only,
+#' not the calculation or positioning of the tick marks. In addition to custom
+#' functions, users can supply one of several convenience strings for common
+#' formats: `"percent"`, `"comma"`, `"dollar"`, `"euro"`, or `"sterling"`.
+#' @param log a character string which contains "x" if the x axis is to be
+#' logarithmic, "y" if the y axis is to be logarithmic and "xy" or "yx" if
+#' both axes are to be logarithmic.
+#' @param flip logical. Should the plot orientation be flipped, so that the
+#' y-axis is on the horizontal plane and the x-axis is on the vertical plane?
+#' Default is FALSE.
#' @param frame.plot a logical indicating whether a box should be drawn around
#' the plot. Can also use `frame` as an acceptable argument alias.
#' The default is to draw a frame if both axis types (set via `axes`, `xaxt`,
@@ -169,7 +194,6 @@
#' arguments from base `plot()` and tries to make the process more seamless
#' with better default behaviour. The default behaviour is determined by (and
#' can be set globally through) the value of `tpar("grid")`.
-#' @param asp the y/xy/x aspect ratio, see `plot.window`.
#' @param palette one of the following options:
#' - NULL (default), in which case the palette will be chosen according to
#' the class and cardinality of the "by" grouping variable. For non-ordered
@@ -194,25 +218,6 @@
#' If too few colours are provided for a discrete (qualitative) set of
#' groups, then the colours will be recycled with a warning. For continuous
#' (sequential) groups, a gradient palette will be interpolated.
-#' @param legend one of the following options:
-#' - NULL (default), in which case the legend will be determined by the
-#' grouping variable. If there is no group variable (i.e., `by` is NULL) then
-#' no legend is drawn. If a grouping variable is detected, then an automatic
-#' legend is drawn to the _outer_ right of the plotting area. Note that the
-#' legend title and categories will automatically be inferred from the `by`
-#' argument and underlying data.
-#' - A convenience string indicating the legend position. The string should
-#' correspond to one of the position keywords supported by the base `legend`
-#' function, e.g. "right", "topleft", "bottom", etc. In addition, `tinyplot`
-#' supports adding a trailing exclamation point to these keywords, e.g.
-#' "right!", "topleft!", or "bottom!". This will place the legend _outside_
-#' the plotting area and adjust the margins of the plot accordingly. Finally,
-#' users can also turn off any legend printing by specifying "none".
-#' - Logical value, where TRUE corresponds to the default case above (same
-#' effect as specifying NULL) and FALSE turns the legend off (same effect as
-#' specifying "none").
-#' - A list or, equivalently, a dedicated `legend()` function with supported
-#' legend arguments, e.g. "bty", "horiz", and so forth.
#' @param col plotting color. Character, integer, or vector of length equal to
#' the number of categories in the `by` variable. See `col`. Note that the
#' default behaviour in `tinyplot` is to vary group colors along any variables
@@ -265,15 +270,6 @@
#' giving the amount by which plotting characters and symbols should be scaled
#' relative to the default. Note that NULL is equivalent to 1.0, while NA
#' renders the characters invisible.
-#' @param restore.par a logical value indicating whether the
-#' \code{\link[graphics]{par}} settings prior to calling `tinyplot` should be
-#' restored on exit. Defaults to FALSE, which makes it possible to add
-#' elements to the plot after it has been drawn. However, note the the outer
-#' margins of the graphics device may have been altered to make space for the
-#' `tinyplot` legend. Users can opt out of this persistent behaviour by
-#' setting to TRUE instead. See also [get_saved_par] for another option to
-#' recover the original \code{\link[graphics]{par}} settings, as well as
-#' longer discussion about the trade-offs involved.
#' @param subset,na.action,drop.unused.levels arguments passed to `model.frame`
#' when extracting the data from `formula` and `data`.
#' @param add logical. If TRUE, then elements are added to the current plot rather
@@ -288,9 +284,22 @@
#' this argument is somewhat experimental and that _no_ internal checking is
#' done for correctness; the provided argument is simply captured and
#' evaluated as-is. See Examples.
-#' @param flip logical. Should the plot orientation be flipped, so that the
-#' y-axis is on the horizontal plane and the x-axis is on the vertical plane?
-#' Default is FALSE.
+#' @param restore.par a logical value indicating whether the
+#' \code{\link[graphics]{par}} settings prior to calling `tinyplot` should be
+#' restored on exit. Defaults to FALSE, which makes it possible to add
+#' elements to the plot after it has been drawn. However, note the the outer
+#' margins of the graphics device may have been altered to make space for the
+#' `tinyplot` legend. Users can opt out of this persistent behaviour by
+#' setting to TRUE instead. See also [get_saved_par] for another option to
+#' recover the original \code{\link[graphics]{par}} settings, as well as
+#' longer discussion about the trade-offs involved.
+#' @param empty logical indicating whether the interior plot region should be
+#' left empty. The default is `FALSE`. Setting to `TRUE` has a similar effect
+#' to invoking `type = "n"` above, except that any legend artifacts owing to a
+#' particular plot type (e.g., lines for `type = "l"` or squares for
+#' `type = "area"`) will still be drawn correctly alongside the empty plot. In
+#' contrast,`type = "n"` implicitly assumes a scatterplot and so any legend
+#' will only depict points.
#' @param file character string giving the file path for writing a plot to disk.
#' If specified, the plot will not be displayed interactively, but rather sent
#' to the appropriate external graphics device (i.e.,
@@ -319,11 +328,7 @@
#' @param height numeric giving the plot height in inches. Same considerations as
#' `width` (above) apply, e.g. will default to `tpar("file.height")` if not
#' specified.
-#' @param xaxt,yaxt character specifying the type of x-axis and y-axis, respectively.
-#' See `axes` for the possible values.
-#' @param xaxs,yaxs character specifying the style of the interval calculation used
-#' for the x-axis and y-axis, respectively. See \code{\link[graphics]{par}}
-#' for the possible values.
+#' @param asp the y/xy/x aspect ratio, see `plot.window`.
#' @param ... other graphical parameters. If `type` is a character specification
#' (such as `"hist"`) then any argument names that match those from the corresponding
#' `type_*()` function (such as \code{\link{type_hist}}) are passed on to that.
@@ -340,7 +345,7 @@
#' without causing unexpected changes to the output.
#'
#' @importFrom grDevices axisTicks adjustcolor cairo_pdf colorRampPalette extendrange palette palette.colors palette.pals hcl.colors hcl.pals xy.coords png jpeg pdf svg dev.off dev.new dev.list
-#' @importFrom graphics abline arrows axis Axis box boxplot grconvertX grconvertY hist lines mtext par plot.default plot.new plot.window points polygon polypath segments rect text title
+#' @importFrom graphics abline arrows axis Axis axTicks box boxplot grconvertX grconvertY hist lines mtext par plot.default plot.new plot.window points polygon polypath segments rect text title
#' @importFrom utils modifyList head tail
#' @importFrom stats na.omit
#' @importFrom tools file_ext
@@ -540,25 +545,35 @@ tinyplot =
tinyplot.default = function(
x = NULL,
y = NULL,
+ xmin = NULL,
+ xmax = NULL,
+ ymin = NULL,
+ ymax = NULL,
by = NULL,
facet = NULL,
facet.args = NULL,
data = NULL,
type = NULL,
- xlim = NULL,
- ylim = NULL,
- log = "",
+ legend = NULL,
main = NULL,
sub = NULL,
xlab = NULL,
ylab = NULL,
ann = par("ann"),
+ xlim = NULL,
+ ylim = NULL,
axes = TRUE,
+ xaxt = NULL,
+ yaxt = NULL,
+ xaxs = NULL,
+ yaxs = NULL,
+ xaxl = NULL,
+ yaxl = NULL,
+ log = "",
+ flip = FALSE,
frame.plot = NULL,
- asp = NA,
grid = NULL,
palette = NULL,
- legend = NULL,
pch = NULL,
lty = NULL,
lwd = NULL,
@@ -567,22 +582,14 @@ tinyplot.default = function(
fill = NULL,
alpha = NULL,
cex = 1,
- restore.par = FALSE,
- xmin = NULL,
- xmax = NULL,
- ymin = NULL,
- ymax = NULL,
add = FALSE,
draw = NULL,
+ empty = FALSE,
+ restore.par = FALSE,
file = NULL,
width = NULL,
height = NULL,
- empty = FALSE,
- xaxt = NULL,
- yaxt = NULL,
- flip = FALSE,
- xaxs = NULL,
- yaxs = NULL,
+ asp = NA,
...) {
par_first = get_saved_par("first")
if (is.null(par_first)) set_saved_par("first", par())
@@ -779,10 +786,12 @@ tinyplot.default = function(
palette = palette,
ribbon.alpha = ribbon.alpha,
xaxt = xaxt,
+ xaxl = xaxl,
xlab = xlab,
xlabs = xlabs,
xlim = xlim,
yaxt = yaxt,
+ yaxl = yaxl,
ylab = ylab,
ylim = ylim
)
@@ -813,6 +822,9 @@ tinyplot.default = function(
xaxs_cp = xaxs
xaxs = yaxs
yaxs = xaxs_cp
+ xaxl_cp = xaxl
+ xaxl = yaxl
+ yaxl = xaxl_cp
if (!is.null(log)) {
log = if (log == "x") "y" else if (log == "y") "x" else log
}
@@ -828,7 +840,7 @@ tinyplot.default = function(
datapoints[["xmax"]] = if (!is.null(datapoints[["ymax"]])) datapoints[["ymax"]] else NULL
datapoints[["ymax"]] = if (!is.null(xmax_cp)) xmax_cp else NULL
# clean up
- rm(xlim_cp, xlab_cp, xlabs_cp, xaxt_cp, xaxs_cp, x_cp, xmin_cp, xmax_cp)
+ rm(xlim_cp, xlab_cp, xlabs_cp, xaxt_cp, xaxs_cp, xaxl_cp, x_cp, xmin_cp, xmax_cp)
} else {
# We'll let boxplot(..., horizontal = TRUE) handle most of the adjustments
# and just catch a few elements that we draw beforehand.
@@ -1129,11 +1141,12 @@ tinyplot.default = function(
y = datapoints$y,
xmax = datapoints$xmax, xmin = datapoints$xmin,
ymax = datapoints$ymax, ymin = datapoints$ymin,
- xaxt = xaxt, xlabs = xlabs, xlim = xlim,
- yaxt = yaxt, ylabs = ylabs, ylim = ylim,
+ xlabs = xlabs, xlim = xlim,
+ ylabs = ylabs, ylim = ylim,
+ xaxt = xaxt, xaxs = xaxs, xaxl = xaxl,
+ yaxt = yaxt, yaxs = yaxs, yaxl = yaxl,
flip = flip,
- draw = draw,
- xaxs = xaxs, yaxs = yaxs
+ draw = draw
)
list2env(facet_window_args, environment())
diff --git a/R/zzz.R b/R/zzz.R
index b8a375ca..0c5ae07e 100644
--- a/R/zzz.R
+++ b/R/zzz.R
@@ -54,6 +54,7 @@
"split_data",
"type",
"x",
+ "xaxl",
"xaxs",
"xaxt",
"xlabs",
@@ -62,6 +63,7 @@
"xmax",
"xmin",
"y",
+ "yaxl",
"yaxs",
"yaxt",
"ylabs",
diff --git a/inst/tinytest/_tinysnapshot/tinytheme_dynamic_yaxl.svg b/inst/tinytest/_tinysnapshot/tinytheme_dynamic_yaxl.svg
new file mode 100644
index 00000000..94562a16
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/tinytheme_dynamic_yaxl.svg
@@ -0,0 +1,137 @@
+
+
diff --git a/inst/tinytest/_tinysnapshot/xaxl_yaxl.svg b/inst/tinytest/_tinysnapshot/xaxl_yaxl.svg
new file mode 100644
index 00000000..8057601b
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/xaxl_yaxl.svg
@@ -0,0 +1,126 @@
+
+
diff --git a/inst/tinytest/test-misc.R b/inst/tinytest/test-misc.R
index 6da33336..17b36adf 100644
--- a/inst/tinytest/test-misc.R
+++ b/inst/tinytest/test-misc.R
@@ -74,6 +74,15 @@ f = function() {
}
expect_snapshot_plot(f, label = "addTRUE")
+# formatting axis tick labels
+f = function() plt(
+ I(decrease/100) ~ treatment, data = OrchardSprays,
+ xaxl = tolower, yaxl = "percent"
+)
+expect_snapshot_plot(f, label = "xaxl_yaxl")
+
+
+# saving files (here: png)
if (requireNamespace("png", quietly = TRUE)) {
f = function() {
tmp_path = tempfile(fileext = ".png")
diff --git a/inst/tinytest/test-tinytheme.R b/inst/tinytest/test-tinytheme.R
index d89b92bf..f2ba29bf 100644
--- a/inst/tinytest/test-tinytheme.R
+++ b/inst/tinytest/test-tinytheme.R
@@ -79,6 +79,18 @@ expect_snapshot_plot(f, label = "tinytheme_dynamic_dark_facet")
tinytheme()
+# variation with formatted tick labels
+f = function() {
+ tinytheme("clean")
+ plt(
+ I(decrease/100) ~ treatment, data = OrchardSprays,
+ yaxl = "percent"
+ )
+ tinytheme()
+}
+expect_snapshot_plot(f, label = "tinytheme_dynamic_yaxl")
+
+
# flipped jitter and boxplot use special internal logic (because of integer spacing)
f = function() {
diff --git a/man/tinyAxis.Rd b/man/tinyAxis.Rd
index f61b56d2..fc7792d1 100644
--- a/man/tinyAxis.Rd
+++ b/man/tinyAxis.Rd
@@ -4,7 +4,7 @@
\alias{tinyAxis}
\title{auxiliary Axis() interface with different parameter combinations based on type}
\usage{
-tinyAxis(x = NULL, ..., type = "standard")
+tinyAxis(x = NULL, ..., type = "standard", labeller = NULL)
}
\description{
auxiliary Axis() interface with different parameter combinations based on type
diff --git a/man/tinylabel.Rd b/man/tinylabel.Rd
new file mode 100644
index 00000000..53d8239c
--- /dev/null
+++ b/man/tinylabel.Rd
@@ -0,0 +1,22 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/tinylabel.R
+\name{tinylabel}
+\alias{tinylabel}
+\title{Format labels}
+\usage{
+tinylabel(x, labeller = NULL)
+}
+\arguments{
+\item{x}{a numeric or character vector}
+
+\item{labeller}{a formatting function to be applied to \code{x}, e.g. \code{abs},
+\code{topper}, etc. Can also be one of the following convenience strings, for
+which common formatting transformations are provided: \code{"percent"},
+\code{"comma"}, \code{"dollar"}, \code{"euro"}, or \code{"sterling"}.}
+}
+\description{
+Internal function for formatting label appearance, e.g. axis
+ticks labels. This is what the top-level \code{xaxl} and \code{yaxl} arguments
+ultimately get passed to.
+}
+\keyword{internal}
diff --git a/man/tinyplot.Rd b/man/tinyplot.Rd
index f65202c2..799369d3 100644
--- a/man/tinyplot.Rd
+++ b/man/tinyplot.Rd
@@ -13,25 +13,35 @@ tinyplot(x, ...)
\method{tinyplot}{default}(
x = NULL,
y = NULL,
+ xmin = NULL,
+ xmax = NULL,
+ ymin = NULL,
+ ymax = NULL,
by = NULL,
facet = NULL,
facet.args = NULL,
data = NULL,
type = NULL,
- xlim = NULL,
- ylim = NULL,
- log = "",
+ legend = NULL,
main = NULL,
sub = NULL,
xlab = NULL,
ylab = NULL,
ann = par("ann"),
+ xlim = NULL,
+ ylim = NULL,
axes = TRUE,
+ xaxt = NULL,
+ yaxt = NULL,
+ xaxs = NULL,
+ yaxs = NULL,
+ xaxl = NULL,
+ yaxl = NULL,
+ log = "",
+ flip = FALSE,
frame.plot = NULL,
- asp = NA,
grid = NULL,
palette = NULL,
- legend = NULL,
pch = NULL,
lty = NULL,
lwd = NULL,
@@ -40,22 +50,14 @@ tinyplot(x, ...)
fill = NULL,
alpha = NULL,
cex = 1,
- restore.par = FALSE,
- xmin = NULL,
- xmax = NULL,
- ymin = NULL,
- ymax = NULL,
add = FALSE,
draw = NULL,
+ empty = FALSE,
+ restore.par = FALSE,
file = NULL,
width = NULL,
height = NULL,
- empty = FALSE,
- xaxt = NULL,
- yaxt = NULL,
- flip = FALSE,
- xaxs = NULL,
- yaxs = NULL,
+ asp = NA,
...
)
@@ -106,6 +108,12 @@ and \code{y} must be of the same length.}
All remaining arguments from \code{...} can be further graphical parameters, see
\code{\link[graphics]{par}}).}
+\item{xmin, xmax, ymin, ymax}{minimum and maximum coordinates of relevant area
+or interval plot types. Only used when the \code{type} argument is one of
+\code{"rect"} or \code{"segments"} (where all four min-max coordinates are required),
+or \code{"pointrange"}, \code{"errorbar"}, or \code{"ribbon"} (where only \code{ymin} and
+\code{ymax} required alongside \code{x}).}
+
\item{by}{grouping variable(s). The default behaviour is for groups to be
represented in the form of distinct colours, which will also trigger an
automatic legend. (See \code{legend} below for customization options.) However,
@@ -232,15 +240,27 @@ type of plot desired.
}
}}
-\item{xlim}{the x limits (x1, x2) of the plot. Note that x1 > x2 is allowed
-and leads to a ‘reversed axis’. The default value, NULL, indicates that
-the range of the \code{finite} values to be plotted should be used.}
-
-\item{ylim}{the y limits of the plot.}
-
-\item{log}{a character string which contains "x" if the x axis is to be
-logarithmic, "y" if the y axis is to be logarithmic and "xy" or "yx" if
-both axes are to be logarithmic.}
+\item{legend}{one of the following options:
+\itemize{
+\item NULL (default), in which case the legend will be determined by the
+grouping variable. If there is no group variable (i.e., \code{by} is NULL) then
+no legend is drawn. If a grouping variable is detected, then an automatic
+legend is drawn to the \emph{outer} right of the plotting area. Note that the
+legend title and categories will automatically be inferred from the \code{by}
+argument and underlying data.
+\item A convenience string indicating the legend position. The string should
+correspond to one of the position keywords supported by the base \code{legend}
+function, e.g. "right", "topleft", "bottom", etc. In addition, \code{tinyplot}
+supports adding a trailing exclamation point to these keywords, e.g.
+"right!", "topleft!", or "bottom!". This will place the legend \emph{outside}
+the plotting area and adjust the margins of the plot accordingly. Finally,
+users can also turn off any legend printing by specifying "none".
+\item Logical value, where TRUE corresponds to the default case above (same
+effect as specifying NULL) and FALSE turns the legend off (same effect as
+specifying "none").
+\item A list or, equivalently, a dedicated \code{legend()} function with supported
+legend arguments, e.g. "bty", "horiz", and so forth.
+}}
\item{main}{a main title for the plot, see also \code{title}.}
@@ -253,6 +273,12 @@ both axes are to be logarithmic.}
\item{ann}{a logical value indicating whether the default annotation (title
and x and y axis labels) should appear on the plot.}
+\item{xlim}{the x limits (x1, x2) of the plot. Note that x1 > x2 is allowed
+and leads to a ‘reversed axis’. The default value, NULL, indicates that
+the range of the \code{finite} values to be plotted should be used.}
+
+\item{ylim}{the y limits of the plot.}
+
\item{axes}{logical or character. Should axes be drawn (\code{TRUE} or \code{FALSE})?
Or alternatively what type of axes should be drawn: \code{"standard"} (with
axis, ticks, and labels; equivalent to \code{TRUE}), \code{"none"} (no axes;
@@ -261,13 +287,32 @@ equivalent to \code{FALSE}), \code{"ticks"} (only ticks and labels without axis
line and labels but no ticks). To control this separately for the two
axes, use the character specifications for \code{xaxt} and/or \code{yaxt}.}
+\item{xaxt, yaxt}{character specifying the type of x-axis and y-axis, respectively.
+See \code{axes} for the possible values.}
+
+\item{xaxs, yaxs}{character specifying the style of the interval calculation used
+for the x-axis and y-axis, respectively. See \code{\link[graphics]{par}}
+for the possible values.}
+
+\item{xaxl, yaxl}{A formatting function (or character string) to apply to the
+x- or y-axis tick labels. This affects the \emph{appearance} of the labels only,
+not the calculation or positioning of the tick marks. In addition to custom
+functions, users can supply one of several convenience strings for common
+formats: \code{"percent"}, \code{"comma"}, \code{"dollar"}, \code{"euro"}, or \code{"sterling"}.}
+
+\item{log}{a character string which contains "x" if the x axis is to be
+logarithmic, "y" if the y axis is to be logarithmic and "xy" or "yx" if
+both axes are to be logarithmic.}
+
+\item{flip}{logical. Should the plot orientation be flipped, so that the
+y-axis is on the horizontal plane and the x-axis is on the vertical plane?
+Default is FALSE.}
+
\item{frame.plot}{a logical indicating whether a box should be drawn around
the plot. Can also use \code{frame} as an acceptable argument alias.
The default is to draw a frame if both axis types (set via \code{axes}, \code{xaxt},
or \code{yaxt}) include axis lines.}
-\item{asp}{the y/xy/x aspect ratio, see \code{plot.window}.}
-
\item{grid}{argument for plotting a background panel grid, one of either:
\itemize{
\item a logical (i.e., \code{TRUE} to draw the grid), or
@@ -305,28 +350,6 @@ groups, then the colours will be recycled with a warning. For continuous
(sequential) groups, a gradient palette will be interpolated.
}}
-\item{legend}{one of the following options:
-\itemize{
-\item NULL (default), in which case the legend will be determined by the
-grouping variable. If there is no group variable (i.e., \code{by} is NULL) then
-no legend is drawn. If a grouping variable is detected, then an automatic
-legend is drawn to the \emph{outer} right of the plotting area. Note that the
-legend title and categories will automatically be inferred from the \code{by}
-argument and underlying data.
-\item A convenience string indicating the legend position. The string should
-correspond to one of the position keywords supported by the base \code{legend}
-function, e.g. "right", "topleft", "bottom", etc. In addition, \code{tinyplot}
-supports adding a trailing exclamation point to these keywords, e.g.
-"right!", "topleft!", or "bottom!". This will place the legend \emph{outside}
-the plotting area and adjust the margins of the plot accordingly. Finally,
-users can also turn off any legend printing by specifying "none".
-\item Logical value, where TRUE corresponds to the default case above (same
-effect as specifying NULL) and FALSE turns the legend off (same effect as
-specifying "none").
-\item A list or, equivalently, a dedicated \code{legend()} function with supported
-legend arguments, e.g. "bty", "horiz", and so forth.
-}}
-
\item{pch}{plotting "character", i.e., symbol to use. Character, integer, or
vector of length equal to the number of categories in the \code{by} variable.
See \code{pch}. In addition, users can supply a special \code{pch = "by"} convenience
@@ -387,22 +410,6 @@ giving the amount by which plotting characters and symbols should be scaled
relative to the default. Note that NULL is equivalent to 1.0, while NA
renders the characters invisible.}
-\item{restore.par}{a logical value indicating whether the
-\code{\link[graphics]{par}} settings prior to calling \code{tinyplot} should be
-restored on exit. Defaults to FALSE, which makes it possible to add
-elements to the plot after it has been drawn. However, note the the outer
-margins of the graphics device may have been altered to make space for the
-\code{tinyplot} legend. Users can opt out of this persistent behaviour by
-setting to TRUE instead. See also \link{get_saved_par} for another option to
-recover the original \code{\link[graphics]{par}} settings, as well as
-longer discussion about the trade-offs involved.}
-
-\item{xmin, xmax, ymin, ymax}{minimum and maximum coordinates of relevant area
-or interval plot types. Only used when the \code{type} argument is one of
-\code{"rect"} or \code{"segments"} (where all four min-max coordinates are required),
-or \code{"pointrange"}, \code{"errorbar"}, or \code{"ribbon"} (where only \code{ymin} and
-\code{ymax} required alongside \code{x}).}
-
\item{add}{logical. If TRUE, then elements are added to the current plot rather
than drawing a new plot window. Note that the automatic legend for the
added elements will be turned off. See also \link{tinyplot_add}, which provides
@@ -417,6 +424,24 @@ this argument is somewhat experimental and that \emph{no} internal checking is
done for correctness; the provided argument is simply captured and
evaluated as-is. See Examples.}
+\item{empty}{logical indicating whether the interior plot region should be
+left empty. The default is \code{FALSE}. Setting to \code{TRUE} has a similar effect
+to invoking \code{type = "n"} above, except that any legend artifacts owing to a
+particular plot type (e.g., lines for \code{type = "l"} or squares for
+\code{type = "area"}) will still be drawn correctly alongside the empty plot. In
+contrast,\code{type = "n"} implicitly assumes a scatterplot and so any legend
+will only depict points.}
+
+\item{restore.par}{a logical value indicating whether the
+\code{\link[graphics]{par}} settings prior to calling \code{tinyplot} should be
+restored on exit. Defaults to FALSE, which makes it possible to add
+elements to the plot after it has been drawn. However, note the the outer
+margins of the graphics device may have been altered to make space for the
+\code{tinyplot} legend. Users can opt out of this persistent behaviour by
+setting to TRUE instead. See also \link{get_saved_par} for another option to
+recover the original \code{\link[graphics]{par}} settings, as well as
+longer discussion about the trade-offs involved.}
+
\item{file}{character string giving the file path for writing a plot to disk.
If specified, the plot will not be displayed interactively, but rather sent
to the appropriate external graphics device (i.e.,
@@ -448,24 +473,7 @@ graphics windows.}
\code{width} (above) apply, e.g. will default to \code{tpar("file.height")} if not
specified.}
-\item{empty}{logical indicating whether the interior plot region should be
-left empty. The default is \code{FALSE}. Setting to \code{TRUE} has a similar effect
-to invoking \code{type = "n"} above, except that any legend artifacts owing to a
-particular plot type (e.g., lines for \code{type = "l"} or squares for
-\code{type = "area"}) will still be drawn correctly alongside the empty plot. In
-contrast,\code{type = "n"} implicitly assumes a scatterplot and so any legend
-will only depict points.}
-
-\item{xaxt, yaxt}{character specifying the type of x-axis and y-axis, respectively.
-See \code{axes} for the possible values.}
-
-\item{flip}{logical. Should the plot orientation be flipped, so that the
-y-axis is on the horizontal plane and the x-axis is on the vertical plane?
-Default is FALSE.}
-
-\item{xaxs, yaxs}{character specifying the style of the interval calculation used
-for the x-axis and y-axis, respectively. See \code{\link[graphics]{par}}
-for the possible values.}
+\item{asp}{the y/xy/x aspect ratio, see \code{plot.window}.}
\item{formula}{a \code{\link[stats]{formula}} that optionally includes
grouping variable(s) after a vertical bar, e.g. \code{y ~ x | z}. One-sided