I'm having trouble, and I don't know exactly how to explain, so sorry in advance.
I have a script that I'll not put here since it is very large, so let's go directly to the problem.
Since the script generates a logo which is a kind of histogram I'll try to simulate the problem with an example.
I'm using a function to split the histogram according to the number of bars, in the end, it generates a plot with various grobs each on containing a piece of the histogram.
myranges <- function(start, end, step){
starts <- seq(start, end, step+1)
ends <- pmin(starts + step, end)
data.frame(a = starts, b = ends)
}
d <- data.frame(a = letters[1:10] , b = seq(1, 20, by =2 ))
num_bar_per_hist <- 2
p_list <- apply(
myranges(1, nrow(d), num_bar_per_hist - 1),
1,
function(x){
#as.matrix(d[x[1]:x[2]],)
ggplot(d[x[1]:x[2] , ], aes(x=a, y=b)) +
geom_bar(stat = "identity") +
ylim(0,22) +
theme_classic()
}
)
do.call(gridExtra::grid.arrange, c(p_list, ncol=2))
Above, the piece of the script which generates the plot.
I change the var num_bar_per_hist
to split the histogram.
In this example I got this:
If I change the value of num_bar_per_hist
to 5 I got:
These two examples show that the width of each plot keeps the same, also the width of the bars.
But, if I change the num_bar_per_hist
to 3 I got:
What I'd like is keep the width of the bars with the same size. That means, the bar j
should be aligned and with the same width of the bar d
which are right above.
Also, if possible, I'd like not to change the structure of the script (too much), or easy/small changes.
I'm grateful in advance. Thanks
EDIT:
Using cowplot
I could solve part of the problem. (same parameter of 3rd plot)
num_bar_per_hist <- 3
p_list <- apply(
myranges(1, nrow(d), num_bar_per_hist - 1),
1,
function(x){
ggdraw() +
draw_plot(
ggplot(d[x[1]:x[2] , ], aes(x=a, y=b)) +
geom_bar(stat = "identity") +
ylim(0, 22),
width = (x[2] - x[1] + 1) / num_bar_per_hist
)
}
)
do.call(gridExtra::grid.arrange, c(p_list, ncol=2))
This way I got:
This way I'm getting close to the solution. The j
still has not the same width than the others but is too better than the 3rd plot.
I'm still needing some trick or "magic number" to improve the width of the bar. Because of that strategy lead the last grob became thinner than the others. And I just want to keep all bars with the same width independently of the difference of the number of bars each plot has.
you can dig out the number of breaks, and from there modify each plot to ensure they all have as many breaks by adding dummy ones to the x scale,
how_many <- function(p){
gb <- ggplot_build(p)
length(gb$layout$panel_params[[1]][['x.major']])
}
raxe <- function(p, n){
gb <- ggplot_build(p)
x_params <- gb$layout$panel_params[[1]]
ni <- length(x_params[['x.major']])
labels <- x_params[['x.labels']]
if(ni < n){
dummy <- c(labels, paste0("__",letters[seq_len(n-ni)]))
print(dummy)
phantom <- c(labels, rep('', n-ni))
return(p + scale_x_discrete(lim=dummy, labels=phantom))
}
p
}
n_breaks <- sapply(p_list, how_many)
p_list <- lapply(p_list, raxe, max(n_breaks))
egg::ggarrange(plots = p_list, ncol=2)