R将布局对象的网格单位转换为本机 [英] R convert grid units of layout object to native

查看:91
本文介绍了R将布局对象的网格单位转换为本机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题与转换单元有关使用R 中的网格将npc转换为本机.

My problem is somewhat related to Convert units from npc to native using grid in R .

我试图弄清楚某些绘图元素的位置始于ggplot2对象(轴,主绘图等).我发现以下代码:

I'm trying to figure out the location of certain plot elements start in a ggplot2 object (axes, main plot, etc). I found the following code:

rm(list = ls())
library(ggplot2)
library(grid)
library(gtable)

# a dummy plot
g <- ggplot(cars, aes(x = speed, y = dist)) + 
  geom_point()
g

# a layout of each element
obj <- ggplotGrob(g)
l <- gtable:::gtable_layout(obj)
grid:::grid.show.layout(l)

我需要的所有信息都必须位于名为 l 的布局对象中.但是,此对象的高度和宽度很奇怪.即使布局有些吸引,它们也通常为零!我调整了 grid ::: grid.show.layout 以打印其绘制的尺寸:

All the information I need must be in the layout object called l. However, the heights and widths of this objects are rather odd. They are often zero, even though there is something draw for the layout! I tweaked grid:::grid.show.layout to print the sizes of what it's drawing:

# aside from sprintf and cat a copy of grid:::grid.show.layout
foo <- function(l, newpage = TRUE, vp.ex = 0.8, bg = "light grey", 
                cell.border = "blue", cell.fill = "light blue", cell.label = TRUE, 
                label.col = "blue", unit.col = "red", vp = NULL, ...) {
  if (!grid:::is.layout(l)) 
    stop("'l' must be a layout")
  if (newpage) 
    grid.newpage()
  if (!is.null(vp)) 
    pushViewport(vp)
  grid.rect(gp = gpar(col = NULL, fill = bg))
  vp.mid <- viewport(0.5, 0.5, vp.ex, vp.ex, layout = l)
  pushViewport(vp.mid)
  grid.rect(gp = gpar(fill = "white"))
  gp.red <- gpar(col = unit.col)
  objs <- matrix(list(), l$nrow, l$ncol)

  unitType <- "cm"
  for (i in 1L:l$nrow) for (j in 1L:l$ncol) {

    h <- convertX(x = l$heights[i, top = FALSE], unitTo = unitType)
    w <- convertY(x = l$widths[j, top = FALSE], unitTo = unitType)
    s1 <- sprintf("s1: i = %d, j = %d, height = %s, width = %s\n", i, j, h, w)
    cat(s1)

    vp.inner <- viewport(layout.pos.row = i, layout.pos.col = j)
    pushViewport(vp.inner)

    # an attempt so save the drawn objects
    objs[[i, j]] <- grid.rect(gp = gpar(col = cell.border, fill = cell.fill))
    if (cell.label) 
      grid.text(paste0("(", i, ", ", j, ")"), gp = gpar(col = label.col))
    if (j == 1) 
      grid.text(format(l$heights[i, top = FALSE], ...), 
                gp = gp.red, just = c("right", "centre"), x = unit(-0.05, 
                                                                   "inches"), y = unit(0.5, "npc"), rot = 0)
    if (i == l$nrow) 
      grid.text(format(l$widths[j, top = FALSE], ...), 
                gp = gp.red, just = c("centre", "top"), x = unit(0.5, 
                                                                 "npc"), y = unit(-0.05, "inches"), rot = 0)
    if (j == l$ncol) 
      grid.text(format(l$heights[i, top = FALSE], ...), 
                gp = gp.red, just = c("left", "centre"), x = unit(1, 
                                                                  "npc") + unit(0.05, "inches"), y = unit(0.5, 
                                                                                                          "npc"), rot = 0)
    if (i == 1) 
      grid.text(format(l$widths[j, top = FALSE], ...), 
                gp = gp.red, just = c("centre", "bottom"), x = unit(0.5, 
                                                                    "npc"), y = unit(1, "npc") + unit(0.05, "inches"), 
                rot = 0)
    popViewport()
  }
  popViewport()
  if (!is.null(vp)) 
    popViewport()
  return(objs)
}

正在运行 foo(l)打印:

s1: i = 1, j = 1, height = 0.193302891933029cm, width = 0.193302891933029cm
...
s1: i = 7, j = 5, height = 0cm, width = 0cm
...
s1: i = 12, j = 9, height = 0.193302891933029cm, width = 0.193302891933029cm

奇怪的是,使用 browser 逐步执行该函数,显示i = 7,j = 5打印出中心的最大矩形,但大小为0cm,0cm!原始单位(分别为1null,1null).

The weird thing is, stepping through the function withbrowser shows that i = 7, j = 5 prints the biggest rectangle in the center, yet the size is 0cm, 0cm! The original units (were 1null, 1null).

所以我的问题是,如何获取以npc/本机单位表示的矩形的大小/坐标?我很高兴在整个结构中进行迭代,但是我想转换为每个矩形的单位都变得有意义.理想情况下,我会为每个布局元素获取由 grid.rect 绘制的四个角的位置,以npc或设备的本机单位为单位.

So my question is, How do I obtain the sizes/ coordinates of the rectangles in npc/ native units? I'm perfectly happy iterating through the entire structure, but I would like to convert the units of each rectangle into something sensible. Ideally, I obtain for each layout element the position of the four corners drawn by grid.rect in npc or native units of the device.

有什么想法吗?

推荐答案

对不起,您还没有完全回答您的问题,但是我有几点评论可能会提供参考. null 单位与 0cm 0inch 单位不同. null 单位是一种占位符值:首先放置具有其他单位的所有内容,然后在 null 单位对象之间分配剩余空间.这种划分一次发生在一个级别上,因此父对象中的 null 单元与子对象中的单元解释不同.

Sorry for not completely answering your question, but I have a few comments that could be informative. null units are not the same as 0cm or 0inch units. null units are kind of a placeholder value: first place everything that has other units, then divide the remaining space among null unit objects. This division occurs at one level at a time, so null units in a parent object are interpreted differently than those in a child object.

实际的 null 单位对应的是未知的,直到绘制绘图为止:您会注意到,如果在图形设备中调整绘图的大小,则轴标题和其他元素通常保持相同的大小,而面板的大小会根据窗口的大小进行调整.

What actual null units correspond to is not known until the plot is drawn: you can notice if you resize your plot in the graphics device, that axes titles and other elements typically remain the same size whereas the size of your panel adjusts to the size of the window.

出于所有其他目的(例如转换为其他单位),它们具有零宽度/零高度,因为首先计算其他所有内容,解释了为什么在函数中进行转换时会找到零单位.

For all other purposes, such as conversion to other units, they have zero-width/zero-height because everything else is calculated first, explaining why you find zero units if you convert these in your function.

因此,除非您为绘图指定了精确的预定义尺寸,否则您将不知道空"单位是什么.

Hence, unless you have exact, predefined dimensions for your plot you cannot know what the 'null' units will be.

您的评论很有道理,我试图找出一种报告以 null 单位定义的面板组的确切宽度和高度的方法,但是它依赖于首先绘制图,所以它不是一个先验值.

Your comment makes sense, and I tried to figure out a way to report the exact width and height of the panel grob defined in null units, but it relies of drawing the plot first, so it's not an a priori value.

# Assume g is your plot
gt <- ggplotGrob(g)
is_panel <- grep("panel", gt$layout$name)
# Re-class the panel to a custom class
class(gt$grobs[[is_panel]]) <- c("size_reporter", class(gt$grobs[[is_panel]]))

# The grid package calls makeContent just before drawing, so we can put code 
# here that reports the size
makeContent.size_reporter <- function(x) {
  print(paste0("width: ", convertWidth(x$wrapvp$width, "cm")))
  print(paste0("height: ", convertHeight(x$wrapvp$height, "cm")))
  x
}

grid.newpage(); grid.draw(gt)

现在,每次绘制曲线图时,您都会在控制台中看到一条文本,该文本以绝对单位(相对于面板的原点)表示实际尺寸.

Now, everytime you draw the plot, you'll get a text in the console that says what the actual dimensions are in absolute units (relative to the origin of the panel).

这篇关于R将布局对象的网格单位转换为本机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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