Thomas Neitmann
Thomas Neitmann

Reputation: 2722

Custom methods for ggplot object

In {ggcharts} I created the diverging_bar_chat() function which rather than drawing a y axis uses geom_text() to directly annotate the bars.

data(mtcars)
mtcars_z <- dplyr::transmute(
  .data = mtcars[1:10, ],
  model = row.names(mtcars[1:10, ]),
  hpz = scale(hp)
)

(p <- ggcharts::diverging_bar_chart(mtcars_z, model, hpz))

enter image description here

When I add any theme to this function the usual y axis pops up again.

p + ggplot2::theme_bw()

enter image description here

While this is to be expected, it's quite undesirable behavior from a user perspective. That's why I'm looking for ways to add a theme in the usual {ggplot2} manner but always remove the y axis, essentially like this function does:

add_theme <- function(diverging_chart, theme) {
  diverging_chart +
    theme +
    theme(
      axis.ticks.y = element_blank(),
      axis.title.y = element_blank(),
      axis.text.y = element_blank(),
      axis.line.y = element_blank()
    )
}

I have tried to define a S3 class for the output of diverging_bar_chart() to be able to define custom methods. However + only works when both the left hand side and the right hand side inherit from the same class. That's why everything in {ggplot2} inherits from gg.

In the {vctrs} vignette I learned about the notion of double dispatch with S3 vectors. However, trying to implement it did not work for me.

class(p) <- c("diverging_chart", class(p))
`+.diverging_chart.theme` <- function(chart, theme) {
  add_theme(chart, theme)
}
p + theme_bw()

enter image description here

At this point I am stuck. My only remaining idea would be to create an S4 class but I'd like to avoid that if possible.

Upvotes: 0

Views: 70

Answers (1)

teunbrand
teunbrand

Reputation: 38063

I think there is a far simpler solution than trying to get the S3 double dispatch working for LHS objects in ggplot's + operator, and that is to simply set the y-axis guide to an empty guide.

As package developer it shouldn't be too difficult to implement this at the correct level.

Illustrated below:

library(ggplot2)
library(ggcharts)

data(mtcars)
mtcars_z <- dplyr::transmute(
  .data = mtcars[1:10, ],
  model = row.names(mtcars[1:10, ]),
  hpz = scale(hp)
)

div_bar_chart <- function(data, ...) {
  ggcharts::diverging_bar_chart(data, ...) +
    guides(y = guide_none())
}

(p <- div_bar_chart(mtcars_z, model, hpz))

p + theme_bw()

Created on 2020-06-01 by the reprex package (v0.3.0)

As an aside, the developer of the 'ggally' package also proposed custom LHS methods for the + operator here.

Upvotes: 3

Related Questions