Changing the `panel_params` in the ggextension


This is a follow up to this question. Although I think I've figured out most of the things that I would like to do, I still cannot modify the layout and panel_params parameters. I can technically assign new values to them, but ggplot doesn't use them. This suggests that I'm not changing them at the right place.

Here is the code for geom_sand. And here is an example:

df <- data.frame(
    x = runif(10, -10, 10),
    y = runif(10, -10, 10)

ggplot(df, aes(x = x, y = y)) +
    geom_sand(size = 2, hl = 5, vl = 5)

What I'd like to happen is for me to be able to change the x.range and y.range and later on maybe change the x.labels and y.labels. You can find my attempts on line 105 to 108, as:

        panel_params$x.range <- c(-15, 15)
        panel_params$y.range <- c(-15, 15)

        panel_params$y.labels <- c("10", "15")

I'd appreciate any help or a document that I can refer too. Unfortunately, the official documentation on extending ggplot are not very elaborate compared to the capabilities of ggplot.

Just on the off-chance that you are not aware of this vignette:

1 Like

See also Thomas Lin Pedersen's slide deck on same:

It's also useful to look at the code from other packages that extend ggplot2, and there are quite a few!

See, for example, cowplot:

I'm actually studying many ggplot packages, even the ggplot source, but for some reasons I couldn't find what I'm looking for. I don't see people actually modifying some of the things that I'd like to change.

Thanks for the package. I'll take a look, maybe I can find something there.

I haven't developed a ggplot extension, but it's possible that some of the things that seem immutable come from grid.

I'm aware of this but it does not answer my question. I can see that it's possible to change the layout through a new facet but that's not what I would like to do. I think that I need to change them in the geom_*. I might be wrong, but I know that I don't want to define a new facet.

I know about grid, but not in detail. I know that grid is technically the last resort. When I realize that I cannot draw what I want by ggplot2 class, then I need to draw everything manually and build it up. I am still not convinced if that's the case.

Do you maybe know anybody who might have more experience with the ggextensions?

The developers/maintainers of ggplot2 extension packages. ¯\(°_o)/¯

Heading to the GitHub then! :crazy_face: :smile:


Hey @mrmsdbdl, sorry for the late reply! With what you're telling me, it seems like this kind of plot you want your extension to produce involves a few parts, including:

  • a combination of geoms (ie. points + segments + vertical and horizontal lines);
  • altered scales; and
  • altered ticks (or just the look of the ticks?)

You've said that it's easy for you to produce a plot like this yourself with ggplot2 but that you're trying to work out how to package this. I wonder if you're not overthinking things by trying to create custom components for all aspects of this. After all, a function can either return a completed (or partially completed) ggplot or a list of ggplot components that can be added to another plot. For example:

#' @export
ggsand <- function(data, xline = 0, yline = 0) {
  ggplot(data, aes(x = x, y = y)) +
    geom_hline(yintercept = yline) +
    geom_vline(xintercept = xline) +
    geom_point() +
    geom_segment() +                           # or geom_path
    scale_x_continuous(limits = c(0, 10)) +
    scale_y_continuous(limits = c(3, 9)) +     # or whatever custom limits you want
      axis.tick.x = element_line(size = 3))


sand_elements <- list(
  geom_hline(yintercept = 0),                # er, these might need to be fixed
  geom_vline(xintercept = 0),                # or assumed you do it this way
  geom_segment(),                            # or geom_path
  scale_x_continuous(limits = c(0, 10)),
  scale_y_continuous(limits = c(3, 9)),      # or whatever custom limits you want
    axis.tick.x = element_line(size = 3)))

ggplot(data, aes(x = x, y = y)) + sand_elements

Now, that doesn't help you with your custom geom/stat: it sounds like you want geom_segment or geom_points (or both) to be doing some sort of computation on the given data before drawing the segments/points. So you'll need a custom stat or geom(s) for that. But if you take this approach, it means, you can leverage ggplot's existing modularity as much as possible and just focus on the part where you actually need it to do something new (rather than trying to come up with a custom component that completely rewrites the whole build process).

You can have a package that exports both the custom component and also the helper function to build the complete plot (so that people can decide whether they want the easy plot generation or to do it themselves), or you can choose to just export the helper function and just use the custom component to abstract the hard work away yourself. What do you think?


Hi @rensa, thanks for your nice reply. As you mentioned, I need to compute some statistics over the data to figure out the position of lines and some other geometries. So, defining a custom stat and geom is what I should do. However, the problem arises when I need to modify the panel.

I kind of like your solution actually to have the custom geom_ handle the computation and then I use a set of paramters like sand_elements to push the specific customizations. I also have done some more research and realized that this is the way that ggplot itself handles this situations, and that’s why I couldn’t find any geom that alters the panel_params.

Thanks a lot for the reply. I’ll see how it goes and hopefully I don’t face another issue and you’ll soon here about the result. :crossed_fingers:

1 Like

Yeah, let us know! I'm still learning to write ggplot2 extensions myself (I ended up making a facet spec recently), so I'm interested to watch others go through the same learning process :smile: