如何使用`grid`创建成对图(矩阵状图)?

时间:2013-07-27 14:56:57

标签: r r-grid

我正在grid尝试我的第一步纯粹。作为练习,我想创建一个纯粹基于pairs()的对图(类似于grid)。下面的函数myplotGrob应该创建网格对象(grob;或gTree)并返回对象。

我不确定 什么是最好的继续方式。应该使用哪些单位? (也试过"null"frameGrob是否意味着设置布局? (这是我从Paul Murrell的书中所理解的)我如何选择/调整视口以便获得所需的图形(到目前为止,我只看到一团糟)是否需要预先设置布局或是否最好只是逐步“连接”其他面板以获得(4,4)绘图矩阵?

require(grid)
require(mvtnorm)

set.seed(271)
X <- rmvnorm(1000, mean=1:4, sigma=diag(4:1)) # goal: draw this in a pairs plot

## auxiliary function
panel <- function(x, y) pointsGrob(x=x, y=y, name="panel", gp=gpar(), vp=NULL)

## creates and returns a gTree (class)
myplotGrob <- function(X, name=NULL, gp=NULL, vp=NULL)
{
    ## x-axis grob

    ## y-axis grob

    ## ...

    ## set up layout
    layout <- grid.layout(4, 4, # (4, 4) matrix
                          widths=rep(0.25, 4), heights=rep(0.25, 4),
                          default.units="npc")
    ## pushViewport(viewport(layout=layout)) # required???

    all <- frameGrob(layout=layout) # produces a gTree without children
    for(i in 1:4) {
        for(j in 1:4) {
            ## group grobs together
            gt <- gTree(X,
                        children=gList(panel(X[,i], X[,j])),
                        name=name, gp=gp, vp=vp, cl="myplotGrob")
            all <- placeGrob(all, gt, row=i, col=j)
        }
    }
    all
}

## draw the gTree
grid.myplot <- function(...) grid.draw(myplotGrob(...))

## call
grid.myplot(X)

更新

正如它所要求的那样,这里是我想到的原始问题的设计/布局(上面只是一个最小/学习的例子)。以厘米为单位的单位对我来说(最后它们应该是“相对的”)。当然,面板的数量可能会有所不同。我希望所有部件都是网格对象,这样创建图形的功能将返回一个对象(无需打印/绘图)。这样,之后可以修改每个部分。图形应显示尺寸为5(或更小)的数组的结果:一个尺寸显示在行面板[row.vars]中,一个尺寸显示在列面板[col.vars]中,一个尺寸显示在x轴上每个面板[xvar],每个面板可以包含2个不同的数组维度(颜色和线型不同)[我在图纸中使用了dn]。如果当然,如果数组是四维的,那么应该缺少上述设计的第8行。我可以通过网格构建布局,但整个问题是如何从那里继续。这就是我想用上面的“最小例子”来表达的。

enter image description here

2 个答案:

答案 0 :(得分:2)

我认为您可以将任务分为两个主要部分,例如grid.panel()grid.multipanel()

中的基本示例

1-构建一个将生成单个面板的函数,作为gTree返回。您需要弄清楚所有参数,即限制,轴,颜色,形状,网格,坐标......您最终可能会重写格子面板功能和轴,

grid.newpage()
grid::grid.panel(vp=viewport(width=0.8, height=0.8))

enter image description here

2-在布局中组装面板。使用gtable

可以更轻松(更清洁)
library(gtable)

grid.newpage()
lg <- replicate(16, grobTree(rectGrob(), pointsGrob()), simplify=FALSE)

gt <- gtable_matrix("pairs", grobs=matrix(lg, ncol=4),
                    widths=unit(rep(1, 4), "null"),
                    heights=unit(rep(1, 4), "null"))

gt <- gtable_add_col_space(gt, width=unit(0.5,"line"))
gt <- gtable_add_row_space(gt, height=unit(0.5,"line"))
gt <- gtable_add_padding(gt, padding=unit(1,"line"))

grid.draw(gt)

如果你想从头开始构建所有东西,我估计你最终还是要重新发明好一部分gtable。

enter image description here

答案 1 :(得分:1)

这是类似于grid.multipanel()但尝试返回gTree的尝试,更具体地说是你的配对图,

require(grid)
require(mvtnorm)

set.seed(271)
X <- rmvnorm(100, mean=1:4, sigma=diag(4:1)) # goal: draw this in a pairs plot

panelGrob <- function(x=runif(10, -10, 10), y=runif(10, -10, 100), ...,
  xlim = range(x), ylim=range(y),
  axis.x=TRUE, axis.y=TRUE){
  xx <- pretty(x) ; yy <- pretty(y)
  xx <- xx[xx <= xlim[2] & xx >= xlim[1]]
  yy <- yy[yy <= ylim[2] & yy >= ylim[1]]

  r <- rectGrob()
  dvp <- dataViewport(xData=xx, yData=yy)
  p <- pointsGrob(x, y, pch=".", gp=gpar(col="red"), default.units="native",
                  vp = dvp)

  ax <- if(axis.x) xaxisGrob(at=xx, vp=dvp) else nullGrob()
  ay <- if(axis.y) yaxisGrob(at=yy, vp=dvp) else nullGrob()

  grobTree(r, ax, ay, p, ...)
}

grid.panel <- function(...)
  grid.draw(panelGrob(...))

grid.newpage()
grid.panel(vp=viewport(width=0.8, height=0.8))


pairsGrob <- function(X, ..., name=NULL, gp=NULL, vp=NULL){

  N <- NCOL(X)
  layout <- grid.layout(N+1, N+1, 
                        widths=unit(c(2, rep(1, N)), c("lines", rep("null", N))), 
                        heights = unit(c(rep(1, N), 2), c(rep("null", N), "lines")))


  wrap <- function(ii, jj, ...){
    panelGrob(X[,ii], X[,jj], ..., axis.x= ii == N, axis.y = jj == 1,
              vp=viewport(layout.pos.row=ii, layout.pos.col=jj+1))
  }

  rowcol <- expand.grid(ii=seq_len(N), jj=seq_len(N))
  gl <- mapply(wrap, ii=rowcol[,"ii"], jj=rowcol[,"jj"], MoreArgs=list(...),
               SIMPLIFY=FALSE)

  gTree(children=do.call(gList, gl), vp=viewport(layout=layout))
}

grid.pairs <- function(...) grid.draw(pairsGrob(...))

grid.newpage()
grid.pairs(X, xlim=c(-10,10), ylim=c(-10,10))

enter image description here

许多问题已经很明显:i)在布局中添加间距,跟踪正确的视口是很麻烦的; ii)面板功能的大多数参数都是硬连线(点形,颜色,网格,轴标签......),为复杂性的爆炸做好准备,如args(lattice::panel.xyplot); iii)轴的范围应该在一行/列之间匹配,这需要考虑在组中正确地分割数据(在ggplot2或格子中的分面); iv)传奇是重塑网格的另一件事; v)......