ggplot2: Adding secondary transformed x-axis on top of plot

前端 未结 2 1080
孤城傲影
孤城傲影 2020-11-29 06:49

[ Edit April 2016: the solution in this thread no longer displays the added axis correctly - a new thread on this issue has been opened at ggplot2 2.1.0 bro

相关标签:
2条回答
  • 2020-11-29 07:39

    The root of your problem is that you are modifying columns and not rows.

    The setup, with scaled labels on the X-axis of the second plot:

    ## 'base' plot
    p1 <- ggplot(data=LakeLevels) + geom_line(aes(x=Elevation,y=Day)) + 
        scale_x_continuous(name="Elevation (m)",limits=c(75,125))
    
    ## 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)
    

    EDIT to have the grid lines align with the lower axis ticks, replace the above line with: 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]]
    

    Now, you need to make sure you are modifying the correct dimension. Because the new axis is horizontal (a row and not a column), whatever_grob$heights is the vector to modify to change the amount of vertical space in a given row. If you want to add new space, make sure to add a row and not a column (ie. use gtable_add_rows()).

    If you are modifying grobs themselves (in this case we are changing the vertical justification of the ticks), be sure to modify the y (vertical position) rather than x (horizontal position).

    ## 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)
    

    I'll note in passing that gtable_show_layout() is a very, very handy function for figuring out what is going on.

    0 讨论(0)
  • 2020-11-29 07:41

    You can use sec_axis or dup_axis.

    library(ggplot2)
    
    ggplot(mtcars, aes(x=disp, y=mpg, color=as.factor(cyl))) +
      geom_point() +
      labs(x="displacement (cubic inches)", col="# of cylinders") +
      scale_x_continuous(sec.axis=sec_axis(trans=~ . * 0.0163871, name="displacement (L)"))
    

    ggplot2 version 3.1.1

    0 讨论(0)
提交回复
热议问题