ggplot和网格:在ggplot grob中找到点的相对x和y位置 [英] ggplot and grid: Find the relative x and y positions of a point in a ggplot grob

查看:131
本文介绍了ggplot和网格:在ggplot grob中找到点的相对x和y位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用网格视口合并ggplot的多个图,这是必要的(我相信),因为我想旋转图,这在标准ggplot中甚至在gridExtra包中都是不可能的.

I'm combining multiple plots of ggplot, using grid viewports, a necessity (I believe) because I want to rotate a plot, something that is not possible in standard ggplot, and maybe even the gridExtra package.

我想在两条曲线上画一条线,以使相关性更加清晰.但是要确切地知道线在哪里,我需要在ggplot图中绘制一个点的相对位置(grob?).

I want to draw a line across two plots, to make a correlation more clear. But to know exactly where the lines are, I need the relative positions of a point in a ggplot plot (grob?).

我已经举了下面的例子:

I have made the following example:

require(reshape2)
require(grid)
require(ggplot2)


datamat <- matrix(rnorm(50), ncol=5)
cov_mat <- cov(datamat)
cov_mat[lower.tri(cov_mat)] <- NA

data_df <- melt(datamat)
cov_df <- melt(cov_mat)

plot_1 <- ggplot(data_df, aes(x=as.factor(Var2), y=value)) + geom_boxplot()
plot_2 <- ggplot(cov_df, aes(x=Var1, y=Var2, fill=value)) + 
                    geom_tile() +
                    scale_fill_gradient(na.value="transparent") + 
                    coord_fixed() +
                    theme(
                    legend.position="none",
                    plot.background = element_rect(fill = "transparent",colour = NA),
                    panel.grid=element_blank(),
                    panel.background=element_blank(),
                    panel.border = element_blank(),
                    plot.margin = unit(c(0, 0, 0, 0), "npc"),
                    axis.ticks=element_blank(), 
                    axis.title=element_blank(), 
                    axis.text=element_text(size=unit(0,"npc")),
                    )

cov_heatmap <- ggplotGrob(plot_2)
boxplot <- ggplotGrob(plot_1)

grid.newpage()

pushViewport(viewport(height=unit(sqrt(2* 0.4 ^2), 'npc'),
                      width=unit(sqrt(2* 0.4 ^2), 'npc'),
                      x=unit(0.5, 'npc'),
                      y=unit(0.63, 'npc'),
                      angle=-45,
                      clip="on")
            )
grid.draw(cov_heatmap)
upViewport(0)
pushViewport(viewport(height=unit(0.5, 'npc'),
                      width=unit(1, 'npc'),
                      x=unit(0.5, 'npc'),
                      y=unit(0.25, 'npc'),
                      clip="on")
            )
grid.draw(boxplot)

会生成情节

如何找到(假设)箱形图的第一个框的相对x和y位置?以及三角协方差矩阵的相对x和y位置.

How do I find the relative x and y positions of (let's say) the first box of the boxplot? and also the relative x and y positions of the triangular covariance matrix.

我知道我必须研究grob对象boxplot,但是我不知道如何在其中找到相关数据.

I know I have to look into the grob objects boxplot, but I don't know how to find the relevant data there.

有人要求我提供一个图解示例,并手动添加线条,如下所示:

I've been asked to provide an example of a plot, with the lines added manually, shown below:

线从底部图的点到顶部图的块.

The lines come from the points on the bottom plot to the blocks on the top plot.

推荐答案

这是一个老问题,因此答案可能不再相关,但无论如何...

This is an old question, so an answer may no longer be relevant, but anyway ....

这不是简单明了,但是可以使用grid编辑工具来完成.一个人需要沿途收集信息,这使解决方案变得轻而易举.这是一个一次性的解决方案.很大程度上取决于两个ggplots的细节.但是也许这里有足够的人供使用.关于画线的信息不足;我将绘制两条红线:一条是从第一个箱线图的横杆的中心到该热图的左下图块的中心;另一条是从热图的左下方.从第一个箱形图的横杆中心到热图中的下一个图块.

This is not straightforward, but it can be done with grid editing tools. One needs to collect information along the way, and that makes the solution fiddly. This is very much a one-off solution. A lot depends on the specifics of the two ggplots. But maybe there is enough here for someone to use. There was insufficient information about the lines to be drawn; I'll draw two red lines: one from the centre of the crossbar of the first boxplot to the centre of the lower left tile of the heatmap; and one from the centre of the crossbar of the first boxplot to the next tile along in the heatmap.

一些要点:

  1. 要在不同视口之间绘制线.通常,在视口中绘制了异形,但是有两种方法可以在视口中绘制线.我将使用grid函数grid.move.to()grid.line.to().
  2. 可以在组团的结构中找到组团的坐标.那是, 可以提取第一个箱形图,并查看其结构.这 结构将给出晶须段的位置, 横梁为分段,盒子为多边形.
  3. 类似地,可以提取热图,结构将给出 每个矩形左上角的坐标(即, 热图上的每个图块)以及每个图块的宽度和高度 长方形.一点简单的算术将给出坐标 瓷砖的中心.
  4. 但是,矩形的坐标是根据 未旋转的视口.选择相关的矩形时需要格外小心.
  1. Lines are to be drawn across different viewports. Normally, grobs are drawn within viewports, but there are a couple of ways to get lines across viewports. I'll use the grid functions grid.move.to() and grid.line.to().
  2. The coordinates of grobs can be found to the structure of the grobs. That is, one can extract the first boxplot, and look at its structure. The structure will give the positions of segments for the whiskers, a segment for the crossbar, and a polygon for the box.
  3. Similarly, one can extract the heatmap, and the structure will give the coordinates for the upper left corner of each rectangle (i.e., each tile) in the heatmap, and the width and height of each rectangle. A bit of simple arithmetic will give the coordinates for the centre of the tiles.
  4. However, the coordinates for the rectangles are in terms of the unrotated viewport. Some care is needed in selecting the relevant rectangles.


# Draw the plot
require(reshape2)
require(grid)
require(ggplot2)

set.seed(4321) 
datamat <- matrix(rnorm(50), ncol=5)
cov_mat <- cov(datamat)
cov_mat[lower.tri(cov_mat)] <- NA

data_df <- melt(datamat)
cov_df <- melt(cov_mat)

plot_1 <- ggplot(data_df, aes(x=as.factor(Var2), y=value)) + geom_boxplot()
plot_2 <- ggplot(cov_df, aes(x=Var1, y=Var2, fill=value)) + 
                    geom_tile() +
                    scale_fill_gradient(na.value="transparent") + 
                    coord_fixed() +
                    theme(
                    legend.position="none",
                    plot.background = element_rect(fill = "transparent",colour = NA),
                    panel.grid=element_blank(),
                    panel.background=element_blank(),
                    panel.border = element_blank(),
                    plot.margin = unit(c(0, 0, 0, 0), "npc"),
                    axis.ticks=element_blank(), 
                    axis.title=element_blank(), 
                    axis.text=element_text(size=unit(0,"npc")))

cov_heatmap <- ggplotGrob(plot_2)
boxplot <- ggplotGrob(plot_1)

grid.newpage()

pushViewport(viewport(height=unit(sqrt(2* 0.4 ^2), 'npc'),
                      width=unit(sqrt(2* 0.4 ^2), 'npc'),
                      x=unit(0.5, 'npc'),
                      y=unit(0.63, 'npc'),
                      angle=-45,
                      clip="on",
                      name = "heatmap"))
grid.draw(cov_heatmap)
upViewport(0)
pushViewport(viewport(height=unit(0.5, 'npc'),
                      width=unit(1, 'npc'),
                      x=unit(0.5, 'npc'),
                      y=unit(0.25, 'npc'),
                      clip="on",
                      name = "boxplot"))
grid.draw(boxplot)
upViewport(0)


# So that grid can see all the grobs
grid.force()

# Get the names of the grobs
grid.ls()

各部分与面板有关.热图文件的名称为:

The relevant bits are in sections to do with the panels. The name of the heatmap grob is:

geom_rect.rect.2

geom_rect.rect.2

组成第一个箱线图的格罗布的名称是(数字可以不同):

The names of the grobs that make up the first boxplot are (the numbers can be different):

geom_boxplot.gTree.40
      GRID.segments.34
      geom_crossbar.gTree.39
         geom_polygon.polygon.37
         GRID.segments.38

geom_boxplot.gTree.40
       GRID.segments.34
       geom_crossbar.gTree.39
          geom_polygon.polygon.37
          GRID.segments.38

获取热图中矩形的坐标.

To get the coordinates of the rectangles in the heatmap.

names = grid.ls()$name
HMmatch = grep("geom_rect", names, value = TRUE)
hm = grid.get(HMmatch)

str(hm)
hm$x
hm$y
hm$width # heights are equal to the widths
hm$gp$fill

(请注意,将just设置为"left", "top")热图是5 X 5的矩形网格,但是只有上半部分是彩色的,因此在图中可见.选定的两个矩形的坐标为:(0.045,0.227)和(0.227,0.409),每个矩形的宽度和高度为0.182

(Note that just is set to "left", "top") The heatmap is a 5 X 5 grid of rectangles, but only the upper half are coloured, and thus visible in the plot. The coordinates for the two selected rectangles are: (0.045, 0.227) and (0.227, 0.409), and each rectangle has a width and height of 0.182

在第一个箱形图中获取相关点的坐标.

To get the coordinates of the relevant points in the first boxplot.

BPmatch = grep("geom_boxplot.gTree", names, value = TRUE)[-1]
box1 = grid.gget(BPmatch[1])
str(box1)

晶须的x坐标为0.115,横杆的y坐标为.507

The x-coord of the whisker is 0.115, and the y-coord of the crossbar is .507

现在,在两个视口之间绘制线条.这些线是在面板视口中绘制"的,但是热图面板视口的名称与箱线图面板视口的名称相同.为了克服这个困难,我寻找了箱形图视口,然后将其向下推到其面板视口.同样,我查找热图视口,然后向下推至其面板视口.

Now, to draw the lines across the two viewports. The lines are 'drawn' in the panel viewports, but the name of the heatmap panel viewport is the same as the name of the boxplot panel viewport. To overcome this difficulty, I seek the boxplot viewport, then push down to its panel viewport; similarly, I seek the heatmap viewport, then push down to its panel viewport.

## First Line (and points)
seekViewport("boxplot") 
downViewport("panel.7-5-7-5")
grid.move.to(x = .115, y = .503, default.units = "native")
grid.points(x = .115, y = .503, default.units = "native", 
      size = unit(5, "mm"), pch = 16, gp=gpar(col = "red"))


seekViewport("heatmap") 
downViewport("panel.7-5-7-5")
grid.line.to(x = 0.045 + .5*.182, y = 0.227 - .5*.182, default.units = "native", gp = gpar(col = "red", lwd = 2))
grid.points(x = 0.045 + .5*.182, y = 0.227 - .5*.182, default.units = "native", 
      size = unit(5, "mm"), pch = 16, gp=gpar(col = "red"))


## Second line (and points)
seekViewport("boxplot") 
downViewport("panel.7-5-7-5")
grid.move.to(x = .115, y = .503, default.units = "native")


seekViewport("heatmap") 
downViewport("panel.7-5-7-5")
grid.line.to(x = 0.227 + .5*.182, y = 0.409 - .5*.182, default.units = "native", gp = gpar(col = "red", lwd = 2))
grid.points(x = 0.227 + .5*.182, y = 0.409 - .5*.182, default.units = "native", 
      size = unit(5, "mm"), pch = 16, gp=gpar(col = "red"))

享受.

这篇关于ggplot和网格:在ggplot grob中找到点的相对x和y位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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