Background
After reading this beautiful answer on how to extend ggplot and the corresponding vignette I was trying to understand, how to extend ggplot
.
In a nutshell
I understand, how the pieces are put together, but I am missing an important information: how does ggplot
determine the default range for the axis?
Code
Consider the following toy example:
library(grid)
library(ggplot2)
GeomFit <- ggproto("GeomFit", GeomBar,
required_aes = c("x", "y"),
setup_data = .subset2(GeomBar, "setup_data"),
draw_panel = function(self, data, panel_scales, coord, width = NULL) {
bars <- ggproto_parent(GeomBar, self)$draw_panel(data,
panel_scales,
coord)
coords <- coord$transform(data, panel_scales)
tg <- textGrob("test", coords$x, coords$y * 2 - coords$ymin)
grobTree(bars, tg)
}
)
geom_fit <- function(mapping = NULL, data = NULL,
stat = "count", position = "stack",
...,
width = NULL,
binwidth = NULL,
na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE) {
layer(
data = data,
mapping = mapping,
stat = stat,
geom = GeomFit,
position = position,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(
width = width,
na.rm = na.rm,
...
)
)
}
set.seed(1234567)
data_gd <- data.frame(x = letters[1:5],
y = 1:5)
p <- ggplot(data = data_gd, aes(x = x, y = y, fill = x)) +
geom_fit(stat = "identity")
Problem
As you can see, some text is not shown. I assume that ggplot
somehow calculates the ranges for the axis and since it is not aware of the extra space needed for my textGrob
. How can I solve that? (Desired outcome is equivalent to p + expand_limits(y = 10)
NB. Of course I could push the problem to the end user, by requiring to add a manual scale. But ideally I would like the scales to be set up properly.
ggplot
expands the range of the data by multiplicatively and additively. The mult and add factors can set by the user in theexpand
argument of ascale
function. See here for an example. This often comes up when people want the plot to not be expanded at all. In recent versions, you can useexpand_scale
to expand the axis in one direction only.?expand_scale
is a decent place to start. – Gregor Thomaslayer_data(p)
, the y values range from 1-5, so that's the plot's scale range. – Z.Linggplot
know for which range it has to look? With the same data, I can get quite different ranges based on my mapping:d <- data.frame(x = rep(1:10, 10), y = sample(3, 100, TRUE))
:p <- ggplot(d, aes(x = x)); p + geom_bar()
vsp + geom_bar(aes(y=y), stat = "identity")
. So only after we know which mappings we use in thegeom
we can determine the range for the plot. -> 1. which function is responsible for determining the range? 2. from which function is his function called? – thothaltrain_position
function from Layout. One trick I like to use when digging into ggplot objects is to run debug onggplot2:::ggplot_build.ggplot
orggplot2:::ggplot_gtable.ggplot_built
(the two stages ofggplotGrob()
), & check the output in each step to find where the phenomenon of interest (in this case scale creation) happens. Careful though, the rabbit hole can get really, really deep... – Z.Lin