Skip to content

implementation strategy: robust ggplot2 functionality for visualizing vctrs-objects #6184

Open
@fabian-s

Description

@fabian-s

posting here in the hopes of getting developer advice:

TL;DR:

vctrs-objects implemented as list-type vectors fail ggplot2's type checking for (continuous) scales, because scales are determined in train_position before stats are applied, and our vctrs- objects are only converted to x-y-tuples by the specific Stat we implement for our vctrs-class.

we are uncertain what a feasible and sensible strategy is:

  • go the whole sfroute and implement entire custom coordinate systems etc (seems like it might be overkill in our case)
  • just implement new primary scale types specifically for our vctrs-objects (how?)
  • something else entirely?

we would appreciate any guidance or pointers to existing implementations solving similar issues.

more details:

Our package tf defines a vctrs-class tf for vectors of functions --basically: lists of 2-column matrices containing $(t, f_i(t))$-tuples.
We were able to define a custom StatTf and some custom geoms based on it (e.g. geom-spaghetti) to enable quick plots like this:

> library(tidyfun)
> library(ggplot2)
> d <- data.frame(
+     x = tf_rgp(3), #3 random functions
+     f = factor(c(1,1,2))
+ )    
> ggplot(d) + geom_spaghetti(aes(y = x, col = f))

Image

This works for many different kinds of geoms and facetting etc etc but breaks down currently as soon as we try to use for example scale-transformations, see also tidyfun/tidyfun#135:

> ggplot(d) + geom_spaghetti(aes(y = x, col = f)) + scale_y_reverse()
Error in `as.character()`:
! Can't convert `x` <tfd_reg> to <character>.
Run `rlang::last_trace()` to see where the error occurred.
> rlang::last_trace()
<error/vctrs_error_cast>
Error in `as.character()`:
! Can't convert `x` <tfd_reg> to <character>.
---
Backtrace:1. ├─base (local) `<fn>`(x)
  2. ├─ggplot2:::print.ggplot(x)
  3. │ ├─ggplot2::ggplot_build(x)
  4. │ └─ggplot2:::ggplot_build.ggplot(x)
  5. │   └─layout$train_position(data, scale_x(), scale_y())
  6. │     └─ggplot2 (local) train_position(..., self = self)
  7. │       └─self$facet$train_scales(...)
  8. │         └─ggplot2 (local) train_scales(...)
  9. │           └─ggplot2:::scale_apply(layer_data, y_vars, "train", SCALE_Y, y_scales)
[...]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions