Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Operation on Lists of Plots #186

Closed
billdenney opened this issue Dec 3, 2019 · 3 comments
Closed

Enable Operation on Lists of Plots #186

billdenney opened this issue Dec 3, 2019 · 3 comments

Comments

@billdenney
Copy link

As described in #93, I often operate on many plots that have similar features. I would love it if there were the ability to work with a list of plots as though they were a single plot. I could imagine that this would dovetail in with the request in #7 to print all pages in facet_wrap_paginate() or facet_grid_paginate(). What I'm thinking of would look something like the following, but I can't find a way to make it work with a simple + instead of %+list%:

library(ggplot2)
library(ggforce)

as_gg_list <- function(x) {
  UseMethod("as_gg_list")
}

as_gg_list.gg <- function(x) {
  if (is.null(n_pages(x))) {
    as_gg_list(list(x))
  } else {
    ret <- list()
    for (idx in seq_len(n_pages(x))) {
      new_facet <-
        ggproto(
          NULL, FacetWrapPaginate,
          shrink = x$facet$shrink,
          params = c(
            x$facet$params[setdiff(names(x$facet$params), "page")],
            list(page = idx)
          )
        )
      ret[[idx]] <- x + new_facet
    }
    as_gg_list(ret)
  }
}

as_gg_list.list <- function(x) {
  class(x) <- "gg_list"
  x
}

print.gg_list <- function(x, ..., fig_suffix = "\n\n") {
  for (idx in seq_along(x)) {
    print(x[[idx]])
    cat(fig_suffix)
  }
}

`%+list%` <- function(e1, e2) {
  as_gg_list(
    lapply(X=e1, FUN="+", e2)
  )
}

p <-
  ggplot(diamonds, aes(x=carat, y=price)) +
  geom_hex() +
  facet_wrap_paginate(facets="color", nrow=1, ncol=1)

n_pages(p)

p_list <- as_gg_list(p)
p_list_2 <- p_list %+list% scale_y_log10()

p_list_2 <- p_list + scale_y_log10()
@billdenney
Copy link
Author

I kept bashing my head against it a bit longer, and I came up with an implementation that will work if you use %+% instead of +. If I improved the documentation, do you think this would be a good fit for ggforce? (If so, I'll add documentation and make it into a PR.)

library(ggplot2)
library(ggforce)

as_gg_list <- function(x) {
  UseMethod("as_gg_list")
}

as_gg_list.gg <- function(x) {
  if (is.null(n_pages(x))) {
    as_gg_list(list(x))
  } else {
    ret <- list()
    for (idx in seq_len(n_pages(x))) {
      new_facet <-
        ggproto(
          NULL, FacetWrapPaginate,
          shrink = x$facet$shrink,
          params = c(
            x$facet$params[setdiff(names(x$facet$params), "page")],
            list(page = idx)
          )
        )
      ret[[idx]] <- x + new_facet
    }
    as_gg_list(ret)
  }
}

as_gg_list.list <- function(x) {
  class(x) <- c("gg_list", "gg")
  x
}

print.gg_list <- function(x, ..., fig_suffix = "\n\n") {
  for (idx in seq_along(x)) {
    print(x[[idx]])
    cat(fig_suffix)
  }
}

`%+%` <- function(e1, e2) {
  UseMethod("%+%")
}

`%+%.gg_list` <- function(e1, e2) {
  as_gg_list(
    lapply(X=e1, FUN="+", e2)
  )
}

`%+%.default` <- function(e1, e2) {
  ggplot2::`%+%`(e1, e2)
}

ggplot.list <- function(data=NULL, mapping = aes(), ..., environment = parent.frame()) {
  as_gg_list(
    lapply(
      X=data,
      FUN=ggplot,
      mapping=mapping,
      ...,
      environment=environment
    )
  )
}

d_list <- split(diamonds, f=diamonds$color)
p <-
  ggplot(diamonds, aes(x=carat, y=price)) +
  geom_hex() +
  facet_wrap_paginate(facets="color", nrow=1, ncol=1)

n_pages(p)

p_list <- as_gg_list(p)
p_list_2 <- p_list %+% scale_y_log10()

p_list_3 <-
  ggplot(d_list, aes(x=carat, y=price)) %+%
  geom_hex() %+%
  facet_wrap(~color)

@thomasp85
Copy link
Owner

I don't think this is a good fit for ggforce, as the focus is to provide new geoms/stats/facets etc, not add a new operator

@billdenney
Copy link
Author

In case someone else has this use case, I'm about to release the ggtibble package on CRAN: https://github.com/billdenney/ggtibble

(I agree that it's not a good fit for ggforce-- but knowing of this other package may help others who may find this issue and have the same goal.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants