前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >91-R可视化23-底层绘图系统grid学习之grob对象

91-R可视化23-底层绘图系统grid学习之grob对象

作者头像
北野茶缸子
发布2022-02-08 15:24:36
8050
发布2022-02-08 15:24:36
举报
  • Date : [[2022-01-05_Wed]]
  • Tags : #R/index/02 #R/R可视化 #R/R数据科学 #R/R可视化/grid底层绘图
  • 参考:
    • 4.5 The grid Package | Mastering Software Development in R (bookdown.org)[1]
    • R实战:grid包 - 悦光阴 - 博客园 (cnblogs.com)[2]
    • (11条消息) R语言grid包使用笔记——viewport_数据之美-CSDN博客_r语言grid包[3]

1-基本介绍

grid包是一个底层的绘图系统,能够灵活地控制图形输出的外观和布局,但是grid包不提供创建完整图形的高级绘图系统,例如,ggplot2和lattice,而是提供绘制开发这些高级绘图的基础接口,

比如我目前的业务需求恰好就是常常ggplot 的个性定制无法满足,因此这里作出一些尝试。先从简单的入手。

2-grob 对象

grob 用来控制grid 绘图的主要元素,包括以下方法:circleGrob, linesGrob, polygonGrob, rasterGrob, rectGrob, textGrob, segmentsGrob, legendGrob, xaxisGrob, and yaxisGrob

可见,不仅是常用的一些图形元素linesGrob、rectGrob等,还有图例legendGrob以及坐标xaxisGrob。

此外,除了grid 可以创建grob 对象外,还有其他包包括gridExtra 也可以创建grob 对象如tableGrob。

2.1-第一个grob 对象

我们可以直接通过上述的grob 方法创建对应的grid 对象,比如:

代码语言:javascript
复制
my_circle <- circleGrob(x = 0.5, y = 0.5, r = 0.5,
                        gp = gpar(col = "gray", lty = 3))
grid.draw(my_circle)

不同于ggplot 中,我们直接在图形对象中给如col, alpha 等图形元素赋值或通过aes 设置变量,grob 对象,通过gpar 函数进行设置,并将结果赋值给gp 参数。

这里可以复习一下这些元素:color (col), fill (fill), transparency (alpha), line type (lty), line width (lwd), line end and join styles (lineend and linejoin, respectively), and font elements (fontsize, fontface, fontfamily).

此外,grob 对象绘图,需要使用专门的绘图语句,比如grid.draw或是cowplot 包中的ggdraw

这里建议只选用grid.draw进行操作,二者还是存在一些差别的。

2.2-编辑grob 对象

我们可以使用grid.edit函数,实时对grid 画板上的grob 对象进行修改:

代码语言:javascript
复制
my_circle <- circleGrob(name = "my_circle",x = 0.5, y = 0.5, r = 0.5,
                        gp = gpar(col = "gray", lty = 3))
grid.draw(my_circle)
my_rect <- rectGrob(x = 0.5, y = 0.5, width = 0.8, height = 0.3)
grid.draw(my_rect)
grid.edit("my_circle", gp = gpar(col = "red", lty = 1))

不过需要注意的是,这里Grob/grid 对象在创建的时候,需要设置name 属性,且grid.edit 必须得对经过grid.draw 投递到画板上的grid 对象操作,否则会报错:

代码语言:javascript
复制
> dev.off()
> my_circle <- circleGrob(name = "my_circle",x = 0.5, y = 0.5, r = 0.5,
+                         gp = gpar(col = "gray", lty = 3))
> grid.edit("my_circle", gp = gpar(col = "red", lty = 1))
Error in editDLfromGPath(gPath, specs, strict, grep, global, redraw) : 
  不存在'gPath'(my_circle)

其实ggplot 对象,也是基于grid 系统制作的,所以我们也可以用grid.draw来绘制ggplot 对象:

代码语言:javascript
复制
wc_plot <- ggplot(cars, aes(x = speed, y = dist)) + 
  geom_point()
grid.draw(wc_plot)

那么,我们可不可以通过grid.edit来个性化修改ggplot 上的元素呢?留个坑。

比较简单的是,如果我们再次运行先前的grid 语句,新的grid 会覆盖上去:

代码语言:javascript
复制
wc_plot <- ggplot(cars, aes(x = speed, y = dist)) + 
  geom_point()
grid.draw(wc_plot)
my_circle <- circleGrob(name = "my_circle",x = 0.5, y = 0.5, r = 0.5,
                        gp = gpar(col = "gray", lty = 3))
grid.draw(my_circle)

2.3-编辑ggplot 对象

“啪的一声,很快啊,就来填坑了。”

但是,ggplot 对象并不是像grob 声明函数一样,我们在创建的时候,对其每个元素都进行name 属性的定义的。这不仅麻烦,也没有必要。

那我们该如何对它们进行编辑呢?

这里主要使用force + ls 的组合:

代码语言:javascript
复制
grid.force() # 将grob 对象拆分
grid.ls()

layout
  background.1-9-12-1
  panel.7-5-7-5
    grill.gTree.323
      panel.background..rect.314
      panel.grid.minor.y..polyline.316
      panel.grid.minor.x..polyline.318
      panel.grid.major.y..polyline.320
      panel.grid.major.x..polyline.322
    NULL
    geom_point.points.310
    NULL
    panel.border..zeroGrob.311
  spacer.8-6-8-6
  spacer.8-4-8-4
  spacer.6-6-6-6
  spacer.6-4-6-4
  axis-t.6-5-6-5
  axis-l.7-4-7-4
    NULL
    axis
      axis.1-1-1-1
        GRID.text.330
      axis.1-2-1-2
  axis-r.7-6-7-6
  axis-b.8-5-8-5
    NULL
    axis
      axis.1-1-1-1
      axis.2-1-2-1
        GRID.text.326
  xlab-t.5-5-5-5
  xlab-b.9-5-9-5
    GRID.text.334
  ylab-l.7-3-7-3
    GRID.text.337
  ylab-r.7-7-7-7
  subtitle.4-5-4-5
  title.3-5-3-5
  caption.10-5-10-5
  tag.2-2-2-2

上面的便是按照具体的元素,进行拆分后的各个元素的名称了,比如下面的x坐标轴文本是GRID.text.334,绘图的点就是geom_point.points.310

我们尝试edit 他们从一下:

代码语言:javascript
复制
grid.edit("geom_point.points.310", gp = gpar(col = "red"))
grid.edit("GRID.text.334", gp = gpar(fontface = "bold"))

此外,我们还可以还直接通过ggplotGrob 方法,将ggplot 对象转换为grob 对象。

2.4-将grob 对象组合

上述的步骤里,我们通过grid.force,将ggplot 的grob 元素进行了拆分,那么我们可否将我们自行创建的grob 对象组合呢?

这里可以使用ggplot 包里的方法gTree,将grob 对象组合:

代码语言:javascript
复制
candy <- circleGrob(r = 0.1, x = 0.5, y = 0.6,
                    gp = gpar(col = "pink",
                              lty = 3,
                              lwd = 2))
stick <- segmentsGrob(x0 = 0.5, x1 = 0.5, y0 = 0, y1 = 0.5, gp = gpar(lwd = 2))
lollipop <- gTree(children = gList(candy, stick))
grid.draw(lollipop)

使用gList 将各个对象传递给children。

那么我们能否将grob 对象转换成ggplot 可以操纵的样子呢?

3-其他一些函数

参见:R 数据可视化 —— grid 系统(二) - 名本无名的文章 - 知乎 https://zhuanlan.zhihu.com/p/371124820

我们除了先通过对象函数创建grob 对象,再通过draw 语句绘图外,还可以直接指定输出,并通过name 来设置名称,比如:

代码语言:javascript
复制
grid.points(iris$Petal.Length, iris$Petal.Width, 
            name = "my_point")

参考资料

[1]4.5 The grid Package | Mastering Software Development in R (bookdown.org): https://bookdown.org/rdpeng/RProgDA/the-grid-package.html#overview-of-grid-graphics

[2]R实战:grid包 - 悦光阴 - 博客园 (cnblogs.com): https://www.cnblogs.com/ljhdo/p/4874785.html

[3](11条消息) R语言grid包使用笔记——viewport_数据之美-CSDN博客_r语言grid包: https://blog.csdn.net/vivihe0/article/details/47188329

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-01-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 北野茶缸子 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1-基本介绍
  • 2-grob 对象
    • 2.1-第一个grob 对象
      • 2.2-编辑grob 对象
        • 2.3-编辑ggplot 对象
          • 2.4-将grob 对象组合
            • 参考资料
        • 3-其他一些函数
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档