Reputation: 6755
I have this two data.frames
df1 <-
data.frame(unit = factor(1:20, levels = 20:1),
value = sample(1:10, 20, replace = T))
df2 <-
data.frame(unit =
factor(as.vector(sapply(1:20, FUN = function(x) rep(x, 10))).
levels = 1:20),
time = rep(1:10, 20),
value = sample(1:100, 10*20, replace = T))
Which I want to plot side by side like this:
library(ggplot2)
library(cowplot)
plot_grid(ggplot(df1, aes(x=value,y=unit)) +
geom_bar(stat = 'identity') +
scale_x_continuous(position = "top"),
ggplot(df2, aes(x=time,y=value)) +
geom_line() +
facet_grid(rows = vars(unit), scales = "free_y") +
scale_x_continuous(position = "top") +
theme(axis.text.y = element_text(size=6)),
ncol = 2)
which results in this output
Still, the rows from the two plots, mapping variables from the same unit
are not perfectly aligned:
What's the easiest way to align them programmatically (so that it will also work with a different number of unit
s)? The solution doesn't need to involve the cowplot package.
Upvotes: 1
Views: 257
Reputation: 173793
If we look at the way the plots are aligned, it seems clear that to have the bars matching the corresponding facets, we have to get rid of the space at either end of the bars' y axis. We can do this with scale_y_discrete(expand = c(0, 0))
. We can also scale the width of the bars so that it is equal to the proportion that each of the facet panels takes up in their allotted viewports. Unfortunately this is somewhat dependent on device dimensions. However, a width of 0.8 or 0.9 will get you pretty close.
plot_grid(ggplot(df1, aes(x=value,y=unit)) +
geom_bar(stat = 'identity', width = 0.8) +
scale_x_continuous(position = "top") +
scale_y_discrete(expand = c(0, 0)),
ggplot(df2, aes(x=time,y=value)) +
geom_line() +
facet_grid(rows = vars(unit), scales = "free_y") +
scale_x_continuous(position = "top") +
theme(axis.text.y = element_text(size=6)),
ncol = 2)
Upvotes: 2
Reputation: 124013
A simple solution to achieve this is by using facets for the bar plot, too. As long as the spacing between the panels is the same in both plots this should ensure that the bars and the line plots for each group are aligned. Try this:
df1 <-
data.frame(unit = factor(1:20, levels = 20:1),
value = sample(1:10, 20, replace = T))
df2 <-
data.frame(unit = factor(as.vector(sapply(1:20, FUN = function(x) rep(x, 10))), levels = 1:20),
time = rep(1:10, 20),
value = sample(1:100, 10*20, replace = T))
library(ggplot2)
library(cowplot)
plot_grid(ggplot(df1, aes(x=value,y=unit)) +
geom_bar(stat = 'identity') +
facet_grid(rows = vars(unit), scales = "free_y") +
scale_x_continuous(position = "top") +
theme(panel.spacing.y = unit(1, "pt"), strip.text = element_blank()),
ggplot(df2, aes(x=time,y=value)) +
geom_line() +
facet_grid(rows = vars(unit), scales = "free_y") +
scale_x_continuous(position = "top") +
theme(axis.text.y = element_text(size=6), panel.spacing.y = unit(1, "pt")),
ncol = 2)
Upvotes: 2