Skip to content

Commit 932e5f8

Browse files
committed
allow to pass function to referent argument & evaluate via LayerRef
1 parent 562e2e9 commit 932e5f8

7 files changed

Lines changed: 92 additions & 10 deletions

File tree

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: gggda
22
Title: A 'ggplot2' Extension for Geometric Data Analysis
3-
Version: 0.1.1
3+
Version: 0.1.1.0009
44
Authors@R: c(
55
person("Jason Cory", "Brunson", email = "cornelioid@gmail.com",
66
role = c("aut", "cre"), comment = c(ORCID = "0000-0003-3126-9494")),

NEWS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# next version
2+
3+
As with the `data` argument, the `referent` argument of `stat_referent()` can now be passed a function, which will be evaluated at `data` to obtain the reference data for the plot layer.
4+
The evaluation is done during addition of a layer of class `LayerRef`.
5+
16
# gggda 0.1.1
27

38
This patch fixes a bug in the peel stat and adds unit tests for it and the scale stat.

R/stat-referent.r

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,27 @@
1010
#' Often in geometric data analysis a statistical transformation applied to data
1111
#' \eqn{X} will also depend on data \eqn{Y}, for example when drawing the
1212
#' projections of vectors \eqn{X} onto vectors \eqn{Y}. The stat layer
13-
#' `stat_referent()` accepts \eqn{Y} as an argument to the `referent` parameter
13+
#' `stat_referent()` accepts \eqn{Y} as an argument to the `referent` argument
1414
#' and pre-processes them using the existing positional aesthetic mappings to
1515
#' `x` and `y`.
1616
#'
17+
#' If a function is passed to `referent`, then the reference data are obtained
18+
#' by evaluating the function at the primary `data`. Alongside borrowing the
19+
#' aesthetic mappings, the evaluation is done during addition via
20+
#' [ggplot2::ggplot_add()] of the layer of custom class `LayerRef`.
21+
#'
1722
#' The ggproto can be used as a parent to more elaborate statistical
1823
#' transformations, or the stat can be paired with geoms that expect the
19-
#' `referent` parameter and use it to position their transformations of \eqn{X}.
20-
#' It pairs by default to `[ggplot2::geom_blank()]` so as to prevent possibly
24+
#' `referent` argument and use it to position their transformations of \eqn{X}.
25+
#' It pairs by default to [ggplot2::geom_blank()] so as to prevent possibly
2126
#' confusing output.
2227
#'
2328

2429
#' @inheritParams ggplot2::layer
2530
#' @template param-layer
2631
#' @inheritParams ggplot2::ggplot_add
27-
#' @param referent The reference data set; see Details.
32+
#' @param referent The reference data set, admitting the same 3 options as
33+
#' `data`; see Details.
2834
#' @template return-layer
2935
#' @family biplot layers
3036
#' @example inst/examples/ex-stat-referent.r
@@ -82,7 +88,9 @@ StatReferent <- ggproto(
8288
# required `x` and `y` aesthetics should be in `data`
8389
# (code adapted from `ggplot2:::Layer$compute_aesthetics()`)
8490
# NB: No checks are conducted here as in `$compute_aesthetics()`.
91+
# TODO: Maybe do this in `LayerRef()` rather than here?
8592
if (! is.null(params$referent)) {
93+
# replace with mappings as applied to primary data
8694
params$referent <- lapply(
8795
params$mapping,
8896
rlang::eval_tidy, data = as.data.frame(params$referent)
@@ -105,6 +113,11 @@ StatReferent <- ggproto(
105113
#' @export
106114
ggplot_add.LayerRef <- function(object, plot, ...) {
107115

116+
# if function, then replace with evaluation at primary data
117+
if (is.function(object$stat_params$referent)) {
118+
object$stat_params$referent <- object$stat_params$referent(plot$data)
119+
}
120+
108121
# store global position mappings as a parameter
109122
object$stat_params$mapping <- plot$mapping[c("x", "y")]
110123

inst/examples/ex-stat-referent.r

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,19 @@ ggplot(subcars, aes(x = hp00, y = wt)) +
1616
ggplot(subcars, aes(x = hp00, y = wt)) +
1717
coord_equal() +
1818
stat_referent(geom = "point", referent = grad)
19+
20+
# passing a function yields a transformation of the primary data
21+
p <- ggplot(subcars, aes(x = hp00, y = wt)) +
22+
stat_referent(
23+
data = head,
24+
referent = function(d) as.data.frame(lapply(d, mean))
25+
)
26+
b <- ggplot_build(p)
27+
# original data
28+
b@plot@data
29+
# head of original data
30+
b@data[[1]]
31+
# means of original data
32+
b@plot@layers$stat_referent$stat_params$referent
33+
# means of head of original data
34+
as.data.frame(lapply(layer_data(p, 1), mean))

man/stat_referent.Rd

Lines changed: 26 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/stat_rule.Rd

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-stat-referent.r

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,28 @@ test_that("mapping and referent parameters together yield new plotting data", {
4242
expect_equal(names(df2_setup), c("x", "y"))
4343
expect_equal(nrow(df2_setup), 4L)
4444
})
45+
46+
test_that("passing a function to `referent` evaluates it at `data`", {
47+
p <- ggplot(mtcars, aes(x = hp/100, y = wt)) +
48+
stat_referent(
49+
data = head,
50+
referent = function(d) as.data.frame(lapply(d, mean))
51+
)
52+
b <- ggplot_build(p)
53+
# original data
54+
expect_identical(b@plot@data, mtcars)
55+
# head of original data
56+
expect_equal(nrow(b@data[[1]]), 6L)
57+
# means of original data
58+
expect_equal(
59+
b@plot@layers$stat_referent$stat_params$referent,
60+
as.data.frame(lapply(mtcars, mean))
61+
)
62+
# means of head of original data
63+
expect_equal(
64+
lapply(subset(layer_data(p, 1), select = c(x, y)), mean),
65+
lapply(head(subset(transform(mtcars, x = hp/100, y = wt),
66+
select = c(x, y))), mean)
67+
)
68+
69+
})

0 commit comments

Comments
 (0)