我正在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个不同的数组维度(颜色和线型不同)[我在图纸中使用了d
和n
]。如果当然,如果数组是四维的,那么应该缺少上述设计的第8行。我可以通过网格构建布局,但整个问题是如何从那里继续。这就是我想用上面的“最小例子”来表达的。
答案 0 :(得分:2)
我认为您可以将任务分为两个主要部分,例如grid.panel()
和grid.multipanel()
1-构建一个将生成单个面板的函数,作为gTree返回。您需要弄清楚所有参数,即限制,轴,颜色,形状,网格,坐标......您最终可能会重写格子面板功能和轴,
grid.newpage()
grid::grid.panel(vp=viewport(width=0.8, height=0.8))
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。
答案 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))
许多问题已经很明显:i)在布局中添加间距,跟踪正确的视口是很麻烦的; ii)面板功能的大多数参数都是硬连线(点形,颜色,网格,轴标签......),为复杂性的爆炸做好准备,如args(lattice::panel.xyplot)
; iii)轴的范围应该在一行/列之间匹配,这需要考虑在组中正确地分割数据(在ggplot2或格子中的分面); iv)传奇是重塑网格的另一件事; v)......