ggplot2 2.1.0 broke my code? Secondary transformed axis now appears incorrectly

前端 未结 3 525
情歌与酒
情歌与酒 2020-12-17 02:29

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

3条回答
  •  我在风中等你
    2020-12-17 02:51

    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)
    

提交回复
热议问题