I tried adding a little summary table to a plot which I created with ggplot2::ggplot()
. The table is added via gridExtra::tableGrob()
to the saved ggplot object.
My problem is that this seems to change the y-limits of my original plot.
Is there a way to avoid that without having to specify the limits again via ylim()
?
Here is a minimal example for the problem using the ChickWeight dataset:
# load packages
require(ggplot2)
require(gridExtra)
# create plot
plot1 = ggplot(data = ChickWeight, aes(x = Time, y = weight, color = Diet)) +
stat_summary(fun.data = "mean_cl_boot", size = 1, alpha = .5)
plot1
# create table to add to the plot
sum_table = aggregate(ChickWeight$weight,
by=list(ChickWeight$Diet),
FUN = mean)
names(sum_table) = c('Diet', 'Mean')
sum_table = tableGrob(sum_table)
# insert table into plot
plot1 + annotation_custom(sum_table)
EDIT:
I just figured out that it seems to be an issue with stat_summary()
. When I use another geom/layer, then the limits stay as they were in the original plot. Another example for that:
plot2 = ggplot(data = ChickWeight, aes(x = Time, y = weight, color = Diet)) +
geom_jitter()
plot2
plot2 + annotation_custom(sum_table)
The y-range for plot1 is different from plot2, the reason being that annotation_custom
takes its aesthetics from the original aes
statement, not the modified data frame used by stat_summary()
. To get the y-ranges for the two plots to be the same (or roughly the same - see below), stop annotation_custom
getting its aesthetics from the original data. That is, move aes()
inside the stat_summary()
.
# load packages
require(ggplot2)
require(gridExtra)
# create plot
plot1 = ggplot(data = ChickWeight) +
stat_summary(aes(x = Time, y = weight, color = Diet), fun.data = "mean_cl_boot", size = 1, alpha = .5)
plot1
# create table to add to the plot
sum_table = aggregate(ChickWeight$weight,
by=list(ChickWeight$Diet),
FUN = mean)
names(sum_table) = c('Diet', 'Mean')
sum_table = tableGrob(sum_table)
# insert table into plot
plot2 = plot1 + annotation_custom(sum_table, xmin = 10, xmax = 10, ymin = 200, ymax = 200)
plot2
By the way, the reason the two plots will not give the exact same y-range is because of the bootstrap function in stat_summary()
. Indeed, plot p1 repeatedly, and you might notice slight changes in the y-range. Or check the y-ranges in the build data.
Edit Updating to ggplot2 ver 3.0.0
ggplot_build(plot1)$layout$panel_params[[1]]$y.range
ggplot_build(plot2)$layout$panel_params[[1]]$y.range
Recall that ggplot does not evaluate functions until drawing time - each time p1 or p2 is drawn, a new bootstrap sample is selected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With