Reputation: 13
I am trying to stack three graphs using ggplot2 and grid arrange. All three graphs should have have the same x axis (but not sharing), the problem is that all of them are in a different temporal resolution and I am having a hard time to align the axis of the three different plots.
This is what I have:
And I want something similar to this:
Dataset Soil temperature
average
3/1/2018 11:00 9.353692972
3/1/2018 12:00 10.75947564
3/1/2018 13:00 11.56223312
3/1/2018 14:00 11.59511989
3/1/2018 15:00 11.07712308
3/1/2018 16:00 9.762939639
3/1/2018 17:00 7.650089417
3/1/2018 18:00 6.021789611
3/1/2018 19:00 4.844122056
3/1/2018 20:00 3.946675139
3/1/2018 21:00 3.265207733
3/1/2018 22:00 2.751823167
3/1/2018 23:00 2.307551222
3/2/2018 0:00 1.977323322
3/2/2018 1:00 1.714310775
3/2/2018 2:00 1.505199708
3/2/2018 3:00 1.402693267
3/2/2018 4:00 1.384921586
3/2/2018 5:00 1.350009046
....
Dataset ppt
3/1/2018 0
3/2/2018 0
3/3/2018 0
3/4/2018 0
3/5/2018 0
3/6/2018 0
3/7/2018 0
3/8/2018 0
3/9/2018 0
3/10/2018 0
3/11/2018 0
3/12/2018 0
3/13/2018 0
3/14/2018 0
Dataset flux
DPF U N
7.08 0.00 0.00
14 0.01 0.02
22 0.16 0.25
29.21 0.00 0.00
33.88 0.05 0.00
42.08 0.00 0.00
code
# define sheets
hourly <- read_excel("ashland2_graphs.xlsx", sheet = 'Hourly')
daily <- read_excel("ashland2_graphs.xlsx", sheet = 'Climate')
nh3flux <-read_excel('ashland2_graphs.xlsx', sheet = 'flux')
# define soil temp
soiltemp <- as.numeric(as.character(hourly$average))
# soil temperature graph
# define x axis
x = c(1:length(soiltemp))
fig1 <- ggplot()+
geom_line(aes(x=x,y = soiltemp), stat = 'identity') +
scale_x_continuous(breaks = seq(1, length(soiltemp), by = 240),
label = c('0', '10', '20', '30', '40'))
# precipitation graph
ppt <- as.numeric(as.character(daily$ppt))
# precip x axis
x2 = c(1:length(ppt))
fig2 <- ggplot(climate) +
geom_bar(aes(x = x2, y = ppt), stat = 'identity', color = "grey") +
scale_y_continuous(expand = c(0, 0))
print(fig2)
# Losses
urea <- as.numeric(as.character(nh3flux$`NH3 Flux g/m2 day-1 - urea`))
nbpt <- as.numeric(as.character(nh3flux$`NH3 Flux g/m2 day-1 - nbpt`))
x3 <- nh3flux$`Days post fertilization`
fig3 <- ggplot(nh3flux) +
geom_point(mapping = aes(x = x3, y = urea)) +
geom_line(mapping = aes(x = x3, y = urea)) +
geom_point(mapping = aes(x = x3, y = nbpt)) +
geom_line(mapping = aes(x = x3, y = nbpt), linetype = 'dashed') +
scale_x_continuous(breaks=seq(0, 45, 10), limits = c(0, 45))
print(fig3)
# stack graphs
grid.arrange(fig3, fig2, fig1, ncol = 1)
Upvotes: 1
Views: 200
Reputation: 11898
For the sake of easy reproducibility, I'll use the mtcars
dataset to
demonstrate how to tackle this. First let's create our three plots:
library(ggplot2)
set.seed(123)
dfs <- split(mtcars, sample(3, nrow(mtcars), replace = TRUE))
# Three plots, with the same x variable but different y and geoms
p1 <- ggplot(dfs[[1]], aes(wt, mpg)) + geom_point()
p2 <- ggplot(dfs[[2]], aes(wt)) + geom_histogram()
p3 <- ggplot(dfs[[3]], aes(wt, cyl)) + geom_smooth()
plots <- list(p1, p2, p3) # easier to work with them all in a list
And here are the plots stacked, exhibiting the same problems that you have:
cowplot::plot_grid(plotlist = plots, ncol = 1)
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
(I'm not using grid.arrange()
, because it lacks some features that we need
for a solution.)
We can identify two problems that need to be taken care of:
The first problem can be addressed by creating a single coordinate object
defining the x-axis limits that we want. With the plots in a list, it's easy
to apply this coordinate system to each of them with lapply()
:
common_coord <- coord_cartesian(xlim = c(1.5, 5.5))
common_x_plots <- lapply(plots, `+`, common_coord)
For your data, setting the limits to c(0, 45)
sould do quite nicely.
The second problem is trickier, and I don't think gridExtra::grid.arrange()
can solve it without quite a bit of extra work. That's why I would recommend
using plot_grid()
from the cowplot package instead: it has an align
option that we can use to line up the plot areas by adding some extra space
between the axis title and axis labels where needed.
With both problems adressed, here's the result:
cowplot::plot_grid(plotlist = common_x_plots, ncol = 1, align = "v")
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
Following this approach, you should be able to achieve what you're looking for with your real data, too.
Created on 2018-08-24 by the reprex package (v0.2.0.9000).
Upvotes: 2