ggplot2:在绘图顶部添加二次变换的 x 轴 [英] ggplot2: Adding secondary transformed x-axis on top of plot

查看:31
本文介绍了ggplot2:在绘图顶部添加二次变换的 x 轴的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[ 2016 年 4 月编辑:此线程中的解决方案不再正确显示添加的轴 - 已在 ggplot2 2.1.0 破坏了我的代码?次要变换轴现在显示不正确 ]

[ 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 broke my code? Secondary transformed axis now appears incorrectly ]

我正在处理缩放的 x 数据,并且需要在图的顶部添加一个未缩放的 x 轴以便于解释.我在 如何将转换后的比例放在 ggplot2 的右侧?.但是,我无法让它在 x 轴上正常工作.我确定我不理解代码的某些部分,但我似乎无法弄清楚它是什么.我试过查看 ggplot2 帮助文件,以及 Wickham 的书 ggplot2: Elegant Graphics For Data Analysis,但如果有人能指点我一些相关文档,我将不胜感激!

I am working with scaled x data, and need to add an unscaled x axis to the top of the plot for easier interpretation. I've come across an approach for adding a secondary a y-axis at How can I put a transformed scale on the right side of a ggplot2?. However, I can't get it to work properly for the x-axis. I'm sure i'm not understanding some part of the code, but I can't seem to figure out what it is. I've tried looking in the ggplot2 help files, and also the Wickham book ggplot2: Elegant Graphics For Data Analysis, but if anyone can point me towards some relevant documentation I would really appreciate it!

我正在处理温度数据,但我将使用上面链接中的湖数据,因为代码是为此编写的.这是该链接的原始代码:

I am working with temperature data, but I will use the lake data from the link above as the code was written for that. Here is the orignal code from that link:

library(ggplot2)
library(gtable)
library(grid)
LakeLevels<-data.frame(Day=c(1:365),Elevation=sin(seq(0,2*pi,2*pi/364))*10+100)
p1 <- ggplot(data=LakeLevels) + geom_line(aes(x=Day,y=Elevation)) + 
      scale_y_continuous(name="Elevation (m)",limits=c(75,125))

p2<-ggplot(data=LakeLevels)+geom_line(aes(x=Day, y=Elevation))+
    scale_y_continuous(name="Elevation (ft)", limits=c(75,125),           
    breaks=c(80,90,100,110,120),
             labels=c("262", "295", "328", "361", "394"))

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

ia <- which(g2$layout$name == "axis-l")
ga <- g2$grobs[[ia]]
ax <- ga$children[[2]]
ax$widths <- rev(ax$widths)
ax$grobs <- rev(ax$grobs)
ax$grobs[[1]]$x <- ax$grobs[[1]]$x - unit(1, "npc") + unit(0.15, "cm")
g <- gtable_add_cols(g, g2$widths[g2$layout[ia, ]$l], length(g$widths) - 1)
g <- gtable_add_grob(g, ax, pp$t, length(g$widths) - 1, pp$b)

# draw it
grid.draw(g)

为了测试添加 x 轴而不是 y 轴的方法,我切换了 x 和 y 轴并将 axis-l 更改为 axis-b给:

To test a method for adding an x-axis instead of y-axis, I switched the x and y axes and changed axis-l to axis-b to give:

library(ggplot2)
library(gtable)
library(grid)
LakeLevels<-data.frame(Day=c(1:365),Elevation=sin(seq(0,2*pi,2*pi/364))*10+100)
p1 <- ggplot(data=LakeLevels) + geom_line(aes(x=Elevation,y=Day)) + 
scale_x_continuous(name="Elevation (m)",limits=c(75,125))

p2<-ggplot(data=LakeLevels)+geom_line(aes(x=Elevation, y=Day))+
scale_x_continuous(name="Elevation (ft)", limits=c(75,125),           
                   breaks=c(80,90,100,110,120),
                   labels=c("262", "295", "328", "361", "394"))

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

ia <- which(g2$layout$name == "axis-b")
ga <- g2$grobs[[ia]]
ax <- ga$children[[2]]
ax$widths <- rev(ax$widths)
ax$grobs <- rev(ax$grobs)
ax$grobs[[1]]$x <- ax$grobs[[1]]$x - unit(1, "npc") + unit(0.15, "cm")
g <- gtable_add_cols(g, g2$widths[g2$layout[ia, ]$l], length(g$widths) - 1)
g <- gtable_add_grob(g, ax, pp$t, length(g$widths) - 1, pp$b)

# draw it
grid.draw(g)

这会产生一个新的 x 轴,但有几个问题:1)它在情节的中间2)它不会为海拔(英尺)"产生一个新的x标签

This produces a new x-axis, but there are a couple of problems: 1) it is in the middle of the plot 2) it does not produce a new x-label for "Elevation (ft)"

我需要轴出现在图的顶部,我需要一个关联的轴标签.谁能告诉我我做错了什么?

此外,如上所述,我正在处理按比例缩放的温度数据,因此理想情况下,刻度不会像本例中那样在顶部和底部轴上对齐.有没有办法在 ggplot2 中做到这一点? 网络上的一个任意示例是:

Also, as mentioned above, I am working with scaled temperature data, so ideally the ticks would not align on the top and bottom axes as they do in this example. Is there any way to do this in ggplot2? An arbitrary example from the web is this:

推荐答案

问题的根源在于您正在修改列而不是行.

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

设置,在第二个图的 X 轴上带有缩放标签:

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 使网格线与下轴刻度对齐,将上面的行替换为:g <- gtable_add_grob(g1, g1$grobs[[which(g1$layout$name=="面板")]], 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]]

现在,您需要确保正在修改正确的尺寸.因为新轴是水平轴(一行而不是一列),whatever_grob$heights 是要修改的向量,以更改给定行中的垂直空间量.如果要添加新空间,请确保添加行而不是列(即使用 gtable_add_rows()).

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()).

如果您正在修改 grobs 本身(在这种情况下,我们正在更改刻度的垂直对齐方式),请务必修改 y(垂直位置)而不是 x(水平位置).

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)

顺便提一下,gtable_show_layout() 是一个非常非常方便的函数,用于确定正在发生的事情.

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

这篇关于ggplot2:在绘图顶部添加二次变换的 x 轴的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆