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 transfo
Updated to ggplot2 v 2.2.1, but it is easier to use sec.axis - see here
Original
Moving axes in ggplot2 became more complex from version 2.1.0. This solution draws on code from older solutions and from code in the cowplot 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).
library(ggplot2) #v 2.2.1
library(gtable) #v 0.2.0
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_path(aes(x = Elevation, y = Day)) +
scale_x_continuous(name = "Elevation (m)", limits = c(75, 125)) +
theme_bw()
## plot with "transformed" axis
p2 <- ggplot(data = LakeLevels) +
geom_path(aes(x = Elevation, y = Day))+
scale_x_continuous(name = "Elevation (ft)", limits = c(75, 125),
breaks = c(80, 90, 100, 110, 120),
labels = round(c(80, 90, 100, 110, 120) * 3.28084)) + ## labels convert to feet
theme_bw()
## Get gtable
g1 <- ggplotGrob(p1)
g2 <- ggplotGrob(p2)
## Get the position of the plot panel in g1
pp <- c(subset(g1$layout, name == "panel", se = t:r))
# Title grobs have margins.
# The margins need to be swapped.
# Function to swap margins -
# taken from the cowplot package:
# https://github.com/wilkelab/cowplot/blob/master/R/switch_axis.R
vinvert_title_grob <- function(grob) {
heights <- grob$heights
grob$heights[1] <- heights[3]
grob$heights[3] <- heights[1]
grob$vp[[1]]$layout$heights[1] <- heights[3]
grob$vp[[1]]$layout$heights[3] <- heights[1]
grob$children[[1]]$hjust <- 1 - grob$children[[1]]$hjust
grob$children[[1]]$vjust <- 1 - grob$children[[1]]$vjust
grob$children[[1]]$y <- unit(1, "npc") - grob$children[[1]]$y
grob
}
# Copy "Elevation (ft)" xlab from g2 and swap margins
index <- which(g2$layout$name == "xlab-b")
xlab <- g2$grobs[[index]]
xlab <- vinvert_title_grob(xlab)
# Put xlab at the top of g1
g1 <- gtable_add_rows(g1, g2$heights[g2$layout[index, ]$t], pp$t-1)
g1 <- gtable_add_grob(g1, xlab, pp$t, pp$l, pp$t, pp$r, clip = "off", name="topxlab")
# Get "feet" axis (axis line, tick marks and tick mark labels) from g2
index <- which(g2$layout$name == "axis-b")
xaxis <- g2$grobs[[index]]
# Move the axis line to the bottom (Not needed in your example)
xaxis$children[[1]]$y <- unit.c(unit(0, "npc"), unit(0, "npc"))
# Swap axis ticks and tick mark labels
ticks <- xaxis$children[[2]]
ticks$heights <- rev(ticks$heights)
ticks$grobs <- rev(ticks$grobs)
# Move tick marks
ticks$grobs[[2]]$y <- ticks$grobs[[2]]$y - unit(1, "npc") + unit(3, "pt")
# Sswap tick mark labels' margins
ticks$grobs[[1]] <- vinvert_title_grob(ticks$grobs[[1]])
# Put ticks and tick mark labels back into xaxis
xaxis$children[[2]] <- ticks
# Add axis to top of g1
g1 <- gtable_add_rows(g1, g2$heights[g2$layout[index, ]$t], pp$t)
g1 <- gtable_add_grob(g1, xaxis, pp$t+1, pp$l, pp$t+1, pp$r, clip = "off", name = "axis-t")
# Add "Stuff" title
titleGrob = textGrob("Stuff", x = 0.9, y = 0.95, gp = gpar(cex = 1.5, fontface = "bold"))
g1 <- gtable_add_grob(g1, titleGrob, pp$t+2, pp$l, pp$t+2, pp$r, name = "Title")
# Draw it
grid.newpage()
grid.draw(g1)