Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 33 additions & 14 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,39 @@ where the formatting is also better._
that the first row sits at the top (again matching `heatmap()`); pass an
explicit `ylim` to override. (#677 @grantmcdermott)

#### Facet improvements

The top-level `facet.args` list argument gains several new (sub-)arguments that
enable finer control and customization of faceted plots:

- `axes`: gives explicit control over which facets draw their own axes: `"all"`,
`"outer"` (drop redundant interior axes), or `"none"`. Previously this was
only achievable as a side effect of `frame.plot = FALSE`, so `axes = "outer"`
now allows redundant axes to be dropped while _keeping_ the facet frames. Left
unspecified, the behaviour is still inferred from whether the plot is framed.
(#661, #673 @grantmcdermott)
- Themes with L-shaped axes (`"classic"`, `"socviz"`, `"tufte"`, and
`"float"`) now default to `facet.axes = "outer"`, so that they drop the
redundant interior axes of faceted plots.
- `labeller`: for formatting facet titles via `tinylabel()`. Accepts the usual
mix of convenience keywords (symbols) known to `tinylabel()`, or formatting
functions. A (named) vector or list can be used to separately format
multi-variable facets, e.g. `labeller = c(country = toupper, size = ",")`.
(#684 @grantmcdermott)
- `prefix`: for adding an informative prefix to facet titles. In its simplest
form, `prefix = TRUE` prepends the facet variable name, e.g. `"vs = 0"` and
`"vs = 1"` (rather than just `"0"` and `"1"`). Like `labeller` above,
multi-variable facets can be prefixed separately via a (named) vector or list,
e.g. `prefix = c(am = "Automatic", vs = "V-shaped")`. (#684 @grantmcdermott)
- `sep`: controls how the individual variables of a multi-variable facet title
are separated, e.g. use `sep = "\n"` to stack on separate lines rather than
concatenating via the default `":"`. (#684 @grantmcdermott)

Note that each of these `facet.args` arguments is paired with an equivalent
`tpar(facet.<arg>)` parameter. For example, call `tpar(facet.axes = "outer")`
to set this behaviour globally. This also means that they can be set as part of
a (custom) theme, e.g. `tinytheme("clean", facet.axes = "outer")`.

#### Other new features

- `type_points()`, `type_lines()`, `type_errorbar()`, and `type_pointrange()`
Expand All @@ -54,20 +87,6 @@ where the formatting is also better._
custom types. See
[Advanced customization](https://grantmcdermott.com/tinyplot/vignettes/types.html#type-hints)
in the `Types` vignette for the list of supported hints. (#543 @grantmcdermott)
- New `axes` argument for `facet.args`, giving explicit control over which
facets draw their own axes: `"all"`, `"outer"` (drop redundant interior
axes), or `"none"`. Previously this was only achievable as a side effect of
`frame.plot = FALSE`, so `facet.args = list(axes = "outer")` now allows
redundant axes to be dropped while _keeping_ the facet frames.
(#661, #673 @grantmcdermott)
- The same behaviour can be set globally via the new `facet.axes` parameter
(note the reverse order), e.g. `tpar(facet.axes = "outer")`, which also
makes it available to themes. A per-call `facet.args = list(axes = ...)`
takes precedence over the global setting, which in turn takes precedence
over the old frame-based inference.
- Accordingly, themes with L-shaped axes (`"classic"`, `"socviz"`, `"tufte"`,
and `"float"`) now default to `facet.axes = "outer"` so that they drop the
redundant interior axes of faceted plots.
- `type_density()` gains an `echo.bw` argument for reporting the smoothing
bandwidth and the number of observations behind it, neither of which is
visible from the curve itself. Destinations are `"sub"`, `"cap"`, and
Expand Down
43 changes: 43 additions & 0 deletions R/assertions.R
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,49 @@ assert_flag = function(x, null.ok = FALSE, name = as.character(substitute(x))) {
}
}

# facet titles prefix: TRUE/FALSE, or custom name(s) for the facet variable(s).
# The latter can be given as a character vector or as a list of strings (the
# vector is the canonical form, but `labeller` takes a list and there is no
# reason to reject the same container here).
assert_facet_prefix = function(x, name = as.character(substitute(x))) {
if (is.null(x)) return(invisible(TRUE))
if (is.logical(x) && length(x) == 1L && !is.na(x)) return(invisible(TRUE))
if ((is.character(x) || is.list(x)) && length(x) >= 1L) {
if (all(vapply(x, is_string1, logical(1L)))) return(invisible(TRUE))
}
stop(
sprintf(
"`%s` must be a logical flag, or facet variable name(s) supplied as a character vector or list of strings.",
name
),
call. = FALSE
)
}

is_string1 = function(x) {
isTRUE(check_string(x)) && !is.na(x)
}

# label formatter passed on to tinylabel(): a function, or one of its
# convenience strings (e.g. "percent"). With `list.ok`, several of them -- as a
# list or character vector -- are allowed too, e.g. one per facet variable.
assert_labeller = function(x, name = as.character(substitute(x)), list.ok = FALSE) {
if (is.null(x) || is_labeller(x)) return(invisible(TRUE))
if (isTRUE(list.ok) && (is.list(x) || is.character(x)) && length(x) >= 1L) {
if (all(vapply(x, is_labeller, logical(1L)))) return(invisible(TRUE))
}
msg = if (isTRUE(list.ok)) {
"`%s` must be a function or a `tinylabel()` convenience string, or a list of them (one per facet variable)."
} else {
"`%s` must be a function, or a `tinylabel()` convenience string."
}
stop(sprintf(msg, name), call. = FALSE)
}

is_labeller = function(x) {
is.function(x) || (is.character(x) && length(x) == 1L && !is.na(x))
}

assert_length = function(x, len = 1, null.ok = FALSE, name = as.character(substitute(x))) {
if (is.null(x) && isTRUE(null.ok)) {
return(invisible(TRUE))
Expand Down
Loading