Some time ago, I inquired about adding a secondary transformed x-axis in ggplot, and Nate Pope provided the excellent solution described at ggplot2: Adding secondary transformed x-axis on top of plot.
That solution worked great for me, and I returned to it hoping it would work for a new project. Unfortunately, the solution doesn't work correctly in the most recent version of ggplot2. Now, running the exact same code leads to a "clipping" of the axis title, as well as overlap of the tick marks and labels. Here is an example, with the problems highlighted in blue:
This example can be reproduced with the following code (this is an exact copy of Nate Pope's code that previously worked marvelously):
library(ggplot2)
library(gtable)
library(grid)
LakeLevels<-data.frame(Day=c(1:365),Elevation=sin(seq(0,2*pi,2*pi/364))*10+100)
## 'base' plot
p1 <- ggplot(data=LakeLevels) + geom_line(aes(x=Elevation,y=Day)) +
scale_x_continuous(name="Elevation (m)",limits=c(75,125)) +
ggtitle("stuff") +
theme(legend.position="none", plot.title=element_text(hjust=0.94, margin = margin(t = 20, b = -20)))
## plot with "transformed" axis
p2<-ggplot(data=LakeLevels)+geom_line(aes(x=Elevation, y=Day))+
scale_x_continuous(name="Elevation (ft)", limits=c(75,125),
breaks=c(90,101,120),
labels=round(c(90,101,120)*3.24084) ## labels convert to feet
)
## extract gtable
g1 <- ggplot_gtable(ggplot_build(p1))
g2 <- ggplot_gtable(ggplot_build(p2))
## overlap the panel of the 2nd plot on that of the 1st plot
pp <- c(subset(g1$layout, name=="panel", se=t:r))
g <- gtable_add_grob(g1, g2$grobs[[which(g2$layout$name=="panel")]], pp$t, pp$l, pp$b,
pp$l)
g <- gtable_add_grob(g1, g1$grobs[[which(g1$layout$name=="panel")]], pp$t, pp$l, pp$b, pp$l)
## steal axis from second plot and modify
ia <- which(g2$layout$name == "axis-b")
ga <- g2$grobs[[ia]]
ax <- ga$children[[2]]
## switch position of ticks and labels
ax$heights <- rev(ax$heights)
ax$grobs <- rev(ax$grobs)
ax$grobs[[2]]$y <- ax$grobs[[2]]$y - unit(1, "npc") + unit(0.15, "cm")
## modify existing row to be tall enough for axis
g$heights[[2]] <- g$heights[g2$layout[ia,]$t]
## add new axis
g <- gtable_add_grob(g, ax, 2, 4, 2, 4)
## add new row for upper axis label
g <- gtable_add_rows(g, g2$heights[1], 1)
g <- gtable_add_grob(g, g2$grob[[6]], 2, 4, 2, 4)
# draw it
grid.draw(g)
Running the above code leads to two critical problems, which I am trying to resolve:
1) How to adjust the x-axis added to the top of the plot to fix the "clipping" and overlap issues?
2) How to include the ggtitle("stuff")
added to the first plot p1
in the final plot?
I've been trying to resolve these problems all afternoon, but cannot seem to solve them. Any help is much appreciated. Thanks!
After some thought, I've confirmed that issue #1 originates from changes to recent versions of ggplot2, and I've also come up with a temporary workaround - installing an old version of ggplot2.
Following Installing older version of R package to install ggplot2 1.0.0, I installed ggplot2 1.0.0 using
which I verified with
Then, re-running the exact code posted above, I was able to produce a plot with the added x-axis correctly displayed:
This is obviously not a very satisfying answer, but it at least works until someone smarter than I can explain why this approach doesn't work in recent versions of ggplot2. :)
So issue #1 from above has been resolved. I'm still haven't resolved issue #2 from above, so would appreciate any insight on that.
Updated to ggplot2 v 2.2.1, but it is easier to use
sec.axis
- see hereOriginal
Moving axes in
ggplot2
became more complex from version 2.1.0. This solution draws on code from older solutions and from code in thecowplot
package.With respect to your second issue, it was easier to construct a separate text grob for the "Stuff" title (rather than dealing with
ggtitle
with its margins).