Skip to content

Commit

Permalink
Transformation suffixes to prefixes (attempt 2) (#410)
Browse files Browse the repository at this point in the history
  • Loading branch information
teunbrand authored Nov 7, 2023
1 parent 727bd71 commit 1ed7b9a
Show file tree
Hide file tree
Showing 39 changed files with 647 additions and 400 deletions.
34 changes: 31 additions & 3 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ S3method(fullseq,Date)
S3method(fullseq,POSIXt)
S3method(fullseq,difftime)
S3method(fullseq,numeric)
S3method(lines,trans)
S3method(lines,transform)
S3method(offset_by,Date)
S3method(offset_by,POSIXt)
S3method(offset_by,difftime)
S3method(offset_by,numeric)
S3method(plot,trans)
S3method(print,trans)
S3method(plot,transform)
S3method(print,transform)
S3method(rescale,"NULL")
S3method(rescale,AsIs)
S3method(rescale,Date)
Expand All @@ -37,6 +37,7 @@ export(abs_area)
export(alpha)
export(area_pal)
export(as.trans)
export(as.transform)
export(asinh_trans)
export(asn_trans)
export(atanh_trans)
Expand Down Expand Up @@ -89,6 +90,7 @@ export(hue_pal)
export(identity_pal)
export(identity_trans)
export(is.trans)
export(is.transform)
export(label_bytes)
export(label_comma)
export(label_currency)
Expand Down Expand Up @@ -121,6 +123,7 @@ export(minor_breaks_n)
export(minor_breaks_width)
export(modulus_trans)
export(muted)
export(new_transform)
export(number)
export(number_bytes)
export(number_bytes_format)
Expand Down Expand Up @@ -185,6 +188,31 @@ export(trans_breaks)
export(trans_format)
export(trans_new)
export(trans_range)
export(transform_asinh)
export(transform_asn)
export(transform_atanh)
export(transform_boxcox)
export(transform_compose)
export(transform_date)
export(transform_exp)
export(transform_hms)
export(transform_identity)
export(transform_log)
export(transform_log10)
export(transform_log1p)
export(transform_log2)
export(transform_logit)
export(transform_modulus)
export(transform_probability)
export(transform_probit)
export(transform_pseudo_log)
export(transform_reciprocal)
export(transform_reverse)
export(transform_sqrt)
export(transform_time)
export(transform_timespan)
export(transform_yj)
export(trim_to_domain)
export(unit_format)
export(viridis_pal)
export(wrap_format)
Expand Down
23 changes: 14 additions & 9 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,27 @@
make it easier to align positive and negative values as figure space takes up
the same amount of space as `-` (#366)
* `label_dollar()` has been superseeded by `label_currency()` for clarity (#344)
* `sqrt_trans()` no longer returns an inverse for values outside of its domain
(#214)
* `transform_sqrt()` no longer returns an inverse for values outside of its
domain (#214)
* Add better support for `difftime` objects. `label_timespan()` adds
functionality for adding correct unit suffix to timespan data,
`breaks_timespan()` adds functionality for finding pleasant breakpoints across
the various bases in time units, while `timespan_trans()` wraps it all
together and provides an alternative to `hms_trans()` (#212)
* Add an inverse (area) hyperbolic sine transformation `asinh_trans()`, which
provides a logarithm-like transformation of a space, but which accommodates
negative values (#297)
* Correct the domain calculation for `compose_trans()` (@mjskay, #408).
the various bases in time units, while `transform_timespan()` wraps it all
together and provides an alternative to `transform_hms()` (#212)
* Add an inverse (area) hyperbolic sine transformation `transform_asinh()`,
which provides a logarithm-like transformation of a space, but which
accommodates negative values (#297)
* Correct the domain calculation for `transform_compose()` (@mjskay, #408).
* Transformation objects can optionally include the derivatives of the transform
and the inverse transform (@mjskay, #322).
* Transformation function have been renamed to `transform_*`-prefixed names
instead of `*_trans`-suffixed names. This allows for a better tab-completion
search of transformations. The S3 class of transformations has been
renamed from `"trans"` to `"transform"`. `new_transform()` replaces
`trans_new()` and `trim_to_domain()` replaces `trans_range()`.
* Palette functions now have the `pal_`-prefix. The old `_pal`-suffixed versions
are kept for backward compatibility.

# scales 1.2.1

* Re-document to fix HTML issues in `.Rd`.
Expand Down
2 changes: 1 addition & 1 deletion R/documentation.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ seealso <- function(pattern) {
paste0("\\code{\\link{", names, "}}", collapse = ", ")
}

seealso_trans <- function() seealso("_trans$")
seealso_transform <- function() seealso("^transform_")

seealso_pal <- function() seealso("^pal_")
6 changes: 3 additions & 3 deletions R/scale-continuous.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@
#' leaves the data unchanged.
#'
#' Built in transformations:
#' \Sexpr[results=rd,stage=build]{scales:::seealso_trans()}.
#' \Sexpr[results=rd,stage=build]{scales:::seealso_transform()}.
#' @export
#' @examples
#' with(mtcars, plot(disp, mpg, cex = cscale(hp, pal_rescale())))
#' with(mtcars, plot(disp, mpg, cex = cscale(hp, pal_rescale(),
#' trans = sqrt_trans()
#' trans = transform_sqrt()
#' )))
#' with(mtcars, plot(disp, mpg, cex = cscale(hp, pal_area())))
#' with(mtcars, plot(disp, mpg,
#' pch = 20, cex = 5,
#' col = cscale(hp, pal_seq_gradient("grey80", "black"))
#' ))
cscale <- function(x, palette, na.value = NA_real_, trans = identity_trans()) {
cscale <- function(x, palette, na.value = NA_real_, trans = transform_identity()) {
if (!is.trans(trans)) cli::cli_abort("{.arg trans} must be a {.cls trans} object")

x <- trans$transform(x)
Expand Down
12 changes: 8 additions & 4 deletions R/trans-compose.R → R/transform-compose.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
#' @examples
#' demo_continuous(10^c(-2:4), trans = "log10", labels = label_log())
#' demo_continuous(10^c(-2:4), trans = c("log10", "reverse"), labels = label_log())
compose_trans <- function(...) {
trans_list <- lapply(list2(...), as.trans)
transform_compose <- function(...) {
trans_list <- lapply(list2(...), as.transform)
if (length(trans_list) == 0) {
cli::cli_abort("{.fun compose_trans} must include at least 1 transformer to compose")
cli::cli_abort("{.fun transform_compose} must include at least 1 transformer to compose")
}

# Resolve domains. First push the domain of the first transformation all the
Expand Down Expand Up @@ -42,7 +42,7 @@ compose_trans <- function(...) {
has_d_transform <- all(lengths(lapply(trans_list, "[[", "d_transform")) > 0)
has_d_inverse <- all(lengths(lapply(trans_list, "[[", "d_inverse")) > 0)

trans_new(
new_transform(
paste0("composition(", paste0(names, collapse = ","), ")"),
transform = function(x) compose_fwd(x, trans_list),
inverse = function(x) compose_rev(x, trans_list),
Expand All @@ -53,6 +53,10 @@ compose_trans <- function(...) {
)
}

#' @export
#' @rdname transform_compose
compose_trans <- transform_compose

compose_fwd <- function(x, trans_list) {
for (trans in trans_list) {
x <- trans$transform(x)
Expand Down
62 changes: 40 additions & 22 deletions R/trans-date.R → R/transform-date.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,28 @@
#' @export
#' @examples
#' years <- seq(as.Date("1910/1/1"), as.Date("1999/1/1"), "years")
#' t <- date_trans()
#' t <- transform_date()
#' t$transform(years)
#' t$inverse(t$transform(years))
#' t$format(t$breaks(range(years)))
date_trans <- function() {
trans_new("date",
transform_date <- function() {
new_transform(
"date",
transform = "from_date",
inverse = "to_date",
breaks = breaks_pretty(),
domain = to_date(c(-Inf, Inf))
)
}

#' @export
#' @rdname transform_date
date_trans <- transform_date

to_date <- function(x) structure(x, class = "Date")
from_date <- function(x) {
if (!inherits(x, "Date")) {
cli::cli_abort("{.fun date_trans} works with objects of class {.cls Date} only")
cli::cli_abort("{.fun transform_date} works with objects of class {.cls Date} only")
}
structure(as.numeric(x), names = names(x))
}
Expand All @@ -31,65 +36,69 @@ from_date <- function(x) {
#' @export
#' @examples
#' hours <- seq(ISOdate(2000, 3, 20, tz = ""), by = "hour", length.out = 10)
#' t <- time_trans()
#' t <- transform_time()
#' t$transform(hours)
#' t$inverse(t$transform(hours))
#' t$format(t$breaks(range(hours)))
time_trans <- function(tz = NULL) {
transform_time <- function(tz = NULL) {
force(tz)
to_time <- function(x) {
structure(x, class = c("POSIXt", "POSIXct"), tzone = tz)
}

from_time <- function(x) {
if (!inherits(x, "POSIXct")) {
cli::cli_abort("{.fun time_trans} works with objects of class {.cls POSIXct} only")
cli::cli_abort("{.fun transform_time} works with objects of class {.cls POSIXct} only")
}
if (is.null(tz)) {
tz <<- attr(as.POSIXlt(x), "tzone")[[1]]
}
structure(as.numeric(x), names = names(x))
}

trans_new("time",
new_transform("time",
transform = "from_time",
inverse = "to_time",
breaks = breaks_pretty(),
domain = to_time(c(-Inf, Inf))
)
}

#' @export
#' @rdname transform_time
time_trans <- transform_time

#' Transformation for times (class hms)
#'
#' `timespan_trans()` provides transformations for data encoding time passed
#' `transform_timespan()` provides transformations for data encoding time passed
#' along with breaks and label formatting showing standard unit of time fitting
#' the range of the data. `hms_trans()` provides the same but using standard hms
#' idioms and formatting.
#' the range of the data. `transform_hms()` provides the same but using standard
#' hms idioms and formatting.
#'
#' @inheritParams label_timespan
#' @export
#' @examples
#' # timespan_trans allows you to specify the time unit numeric data is
#' # transform_timespan allows you to specify the time unit numeric data is
#' # interpreted in
#' min_trans <- timespan_trans("mins")
#' demo_timespan(seq(0, 100), trans = min_trans)
#' trans_min <- transform_timespan("mins")
#' demo_timespan(seq(0, 100), trans = trans_min)
#' # Input already in difftime format is interpreted correctly
#' demo_timespan(as.difftime(seq(0, 100), units = "secs"), trans = min_trans)
#' demo_timespan(as.difftime(seq(0, 100), units = "secs"), trans = trans_min)
#'
#' if (require("hms")) {
#' # hms_trans always assumes seconds
#' # transform_hms always assumes seconds
#' hms <- round(runif(10) * 86400)
#' t <- hms_trans()
#' t <- transform_hms()
#' t$transform(hms)
#' t$inverse(t$transform(hms))
#' t$breaks(hms)
#' # The break labels also follow the hms format
#' demo_timespan(hms, trans = t)
#' }
#'
timespan_trans <- function(unit = c("secs", "mins", "hours", "days", "weeks")) {
transform_timespan <- function(unit = c("secs", "mins", "hours", "days", "weeks")) {
unit <- arg_match(unit)
trans_new(
new_transform(
"timespan",
transform = function(x) {
structure(as.numeric(as.difftime(x, units = unit), units = "secs"), names = names(x))
Expand All @@ -103,10 +112,15 @@ timespan_trans <- function(unit = c("secs", "mins", "hours", "days", "weeks")) {
format = label_timespan(unit)
)
}
#' @rdname timespan_trans

#' @export
hms_trans <- function() {
trans_new(
#' @rdname transform_timespan
timespan_trans <- transform_timespan

#' @rdname transform_timespan
#' @export
transform_hms <- function() {
new_transform(
"hms",
transform = function(x) {
structure(as.numeric(x), names = names(x))
Expand All @@ -116,6 +130,10 @@ hms_trans <- function() {
)
}

#' @rdname transform_timespan
#' @export
hms_trans <- transform_hms

breaks_hms <- function(n = 5) {
base_breaks <- breaks_timespan("secs", n)
function(x) {
Expand Down
Loading

0 comments on commit 1ed7b9a

Please sign in to comment.