R数据可视化grid系统二

中科白癜风 http://baidianfeng.39.net/
R数据可视化——grid系统(二)前言

在前面一节中,我们主要介绍了如何使用grid来生成图形输出,以及图形窗口的布局。利用这些知识,可以很容易地为图形添加注释,编写一些简单的绘图函数

这一节,我们将重点介绍如何使用grid函数来创建和操作图形对象。利用这些信息,可以交互式地编辑和修改图形输出

图形对象1.控制图像输出

我们可以使用图形原语来绘制图形输出,并返回一个图形对象(grob),例如

library(RColorBrewer)grid.circle(name="circles",x=seq(0.1,0.9,length=40),y=0.5+0.4*sin(seq(0,2*pi,length=40)),r=abs(0.1*cos(seq(0,2*pi,length=40))),gp=gpar(col=brewer.pal(40,"Set2")))

这段代码将会绘制一串圆形

同时也会生成一个circlegrob,该对象保存了当前绘制的这些圆形的信息

grid保留了一个显示列表,用于记录当前画布中的所有的viewport和grobs。因此,grid.circle()函数构造的对象也会保存在显示列表中,意味着我们可以根据对象的名称circles来获取、修改该对象

使用grid.get()函数,可以获取该circle对象的拷贝

grid.get("circles")circle[circles]

使用grid.edit()可以用来修改该circle对象的图像属性

grid.edit("circles",gp=gpar(col=brewer.pal(10,"RdBu")))

修改颜色属性之后,会直接显示在图形输出中

还可以使用grid.remove()函数,从显示列表中删除图形对象的输出

grid.remove("circles")

一片空白,什么也没有

1.1标准的函数及参数

控制grobs的函数包括:

所有图像输出函数的第一个参数都是图像对象的名称,如果参数grep=TRUE,可以接受正则表达式对象名称

如果global=TRUE,则会返回显示列表中所有匹配的对象,例如

suffix-c("even","odd")for(iin1:8)grid.circle(name=paste0("circle.",suffix[i%%2+1]),r=(9-i)/20,gp=gpar(col=NA,fill=grey(i/10)))

我们绘制了8个同心圆,并根据奇偶顺序将circlegrob命名为circle.odd和circle.even

然后,我们可以使用grid.edit()函数,修改所有名为circle.odd的grobs的颜色

grid.edit("circle.odd",gp=gpar(fill=brewer.pal(4,"Set3")[4]),global=TRUE)

或者,用正则表达式来匹配以circle开头的grob

grid.edit("circle",gp=gpar(col="#80b1d3",fill="#fdb"),grep=TRUE,global=TRUE)

只要我们知道了grobs的名称,就可以对其获取、修改或删除

而getNames()函数,可以帮助我们获取当前图形中所有grobs的名称

2.grob排布结构

grob的排布结果包括:

gList:包含多个grobs的listgTree:grobs的树形结构,即一个grob中包含其他的grob

例如,对于xaxisgrob

pushViewport(viewport(y=0.5,height=0.5,width=0.5))grid.rect()pushViewport(viewport(y=0.5,height=0.5,width=0.5))grid.xaxis(name="axis1",at=1:4/5)

会包含有多个子grob,如线条,文本等

childNames(grid.get("axis1"))[1]"major""ticks""labels"

如果把xaxisgrob看作为一棵树的根,那么它包含三个子grob。

其中major和ticks是linesgrob,labels为textgrob。

其中at参数设置了轴刻度,我们可以使用grid.edit来修改

grid.edit("axis1",at=1:3/4)

那想要修改labels的格式,怎么办?即如何访问一个对象的子对象呢?

可以使用gPath(grobpath)函数,类似于vpPath,可以使用父节点名称加子节点名称来访问

grid.edit(gPath("axis1","labels"),rot=45)

或者,也可以使用axis1::labels方式来访问

注意:grobs的搜索是深度优先,也就是说,如果在显示列表中遍历到了一个gTreegrob,且未找到匹配项,则会对该grob执行深度优先遍历

这种gTree结构对象,也包含gp和vp参数。

在父节点上设置对应的gp参数值,会作为默认值传递给子对象。例如

grid.xaxis(gp=gpar(col="grey"))

也可以将一个viewport直接作为参数值传递

grid.xaxis(vp=viewport(y=0.75,height=0.5))3.图形对象

在前面的章节中,我们介绍的都是如何使用函数直接生成图形输出并返回图形对象(grob)

在这一节,我们将介绍如果创建grob,但不绘制图形,通过对grob创建及修改,并在最后使用grid.draw()函数来绘制出图形。

每个能产生图形输出和图形对象的grid函数都有一个对应的只创建图形对象,没有图形输出的函数

例如,grid.circle()对应于circleGrob(),grid.edit()对应于editGrob(),在前面的函数表中都有列出

例如

grid.newpage()pushViewport(viewport(width=0.5,height=0.5))#创建x轴对象ag-xaxisGrob(at=1:4/5)#修改对象,将标签的字体变为斜体ag-editGrob(ag,"labels",gp=gpar(fontface="italic"))#绘图grid.draw(ag)

我们可以将不同的grob组合在一起,生成一个复杂的图形。比如

grid.newpage()tg-textGrob("sampletext")rg-rectGrob(width=1.2*grobWidth(tg),height=1.5*grobHeight(tg))boxedText-gTree(children=gList(rg,tg))

我们构建一个名为boxedText的gTree对象,包含其子对象包括一个文本和一个矩形

我们直接可以绘制组合对象

grid.draw(boxedText)

而对该对象的图形属性的修改,会反映到具体的子对象中

grid.draw(editGrob(boxedText,gp=gpar(col="skyblue")))

指定viewport

grid.draw(editGrob(boxedText,vp=viewport(angle=45),gp=gpar(fontsize=18)))3.1捕获输出

在上面的例子中,我们先构建了一个组合对象,然后绘制该对象

还可以反着来,先绘制图形对象,然后对它们进行组合。

使用grid.grab()函数,可以获取当前画布中所有输出的图形对象,并以gTree的形式返回

例如,我们使用ggplot2绘制一个直方图,并获取所有图形对象

ggplot(mpg)+geom_histogram(aes(displ,fill=class),bins=10,position="dodge")histTree-grid.grab()

然后,你可以尝试运行下面的代码

grid.newpage()grid.draw(histTree)

你会发现,可以绘制出一张一模一样的图

也可以使用grid.grabExpr来获取表达式的输出图形对象

grid.grabExpr(print(ggplot(mpg)+geom_histogram(aes(displ,fill=class),bins=10,position="dodge")))4.图形对象的放置

假设我们有一个复杂图形

#文本对象label-textGrob("A\nPlot\nLabel",x=0,just="left")x-seq(0.1,0.9,length=50)y-runif(50,0.1,0.9)#gTree结构图形对象,包括矩形、线图、点图gplot-gTree(children=gList(rectGrob(gp=gpar(col="grey60",fill="#cbd5e8",alpha=0.3)),linesGrob(x,y,gp=gpar(col="#33a02c")),pointsGrob(x,y,pch=16,size=unit(5,"mm"),gp=gpar(col="#fb"))),vp=viewport(width=unit(1,"npc")-unit(5,"mm"),height=unit(1,"npc")-unit(5,"mm")))

我们可以使用上一章节提到的布局方法,将该图像设计为1行2列的布局

layout-grid.layout(nrow=1,ncol=2,widths=unit(c(1,1),c("null","grobwidth"),list(NULL,label)))

然后将图形绘制到指定位置中

pushViewport(viewport(layout=layout))pushViewport(viewport(layout.pos.col=2))grid.draw(label)popViewport()pushViewport(viewport(layout.pos.col=1))grid.draw(gplot)popViewport(2)

但其实,grid提供了更简便的函数用于放置grobs

grid.frame()函数创建一个没有子对象的gTree,可以使用grid.pack()向其中添加子对象,同时确保为每个子对象保留足够的绘图空间

上面的代码可以改写成

grid.newpage()#新建一个空framegrid.frame(name="frame1")#放置gplot对象,在这一阶段,gplot会占据整个framegrid.pack("frame1",gplot)#在frame的右边放置label对象grid.pack("frame1",label,side="right")

这种动态的方式很简便,但是也带来了时间上的花费,随着需要放置的对象越来越多,速度会越来越慢。

另一种替代的方式是,先定义一个布局,然后再放置对象

grid.frame(name="frame1",layout=layout)grid.place("frame1",gplot,col=1)grid.place("frame1",label,col=2)4.1安静模式

在上面两个例子中,每次放置一个grob都会更新一遍图形输出。所以,一个更好的方式是,在安静模式下创建一个frame,然后放置grobs。

安静模式,即使用对象函数frameGrob()和placeGrob()/packGrob创建frame、放置grobs,但是不会输出图形,只有在所有设置完成之后,使用grid.draw一次性绘制

#创建framefg-frameGrob(layout=layout)#添加grobfg-placeGrob(fg,gplot,col=1)fg-placeGrob(fg,label,col=2)#一次性绘制grid.draw(fg)-END-生信学习手册



转载请注明地址:http://www.sanbaicaoasb.com/scls/8529.html
  • 上一篇文章:
  • 下一篇文章: 没有了
  • 热点文章

    • 没有热点文章

    推荐文章

    • 没有推荐文章