答: 扪心自问,meme几何?

在2018-04-06,Y叔推送了一篇文章 扪心自问,meme几何?。从一个不到146行的meme.R出发,提了5个问题。让检查我们的ggplot2的理解程度。

从我第一次接触ggplot2开始,至今差不多过去了2年多时间。Y叔推荐的「ggplot2: 数据分析和图形语法」和「R绘图系统」也被我翻得书页泛黄,加上近日又在学习Hadley写的 extending-ggplot2,近日终于有所悟,尝试解答Y叔提出的几个问题。

1. meme的输出不是图?为什么能画出图?

这一题,Y叔在 R绘图系统 的书评中给出了答案。

感谢译者送我的签名版,这是最全面介绍R绘图系统的书,没有之一。Base因为有大量的绘图函数还大量在使用,但做为新人学习,必须是grid系统!因为图是对象,可以操作,只有在需要渲染成静态图片的时候才产生图片。

更加详细一点,核心语句在于imageGrob <- rasterGrob(x)将读取的图像转成了grid的Grob对象,之后在此基础上构建了p,它继承了memerecordeplot。这里的继承是关键词,也就是第二题的答案所在。

2. 为什么+可以改变图的内容和状态?

解答这一题需要两个关键知识

  1. R语言是一个面向对象编程的语言,里面有一类泛型函数,可以根据你的对象类型自动调用对应的函数。
  2. +是函数。

Y叔为meme对象专门定义了一个泛型函数+.meme, 因此在调用+的时候,也就是调用了+.meme函数。

3. 为什么ggsave能识别meme对象

这一题是讨论ggsave的本质,如果你直接在命令行里敲ggsave,他会输出ggsave的源代码,倒数第二句就是答案所在。

grid.draw(plot)

ggsave在绘图商调用的是grid.draw, 这是用来绘制一个grob对象。而无论是cowplot,还是meme, 它们都建立在grid系统下,也就能够用grid.draw画出来。

而如果你调用的是print(meme),那么泛型函数会尝试调用print.grob

4. 为什么使用传统的出图方式来画meme,在循环中需要显示print(object)?而ggsave则不用?到底区别在那里?

这个问题稍微比较复杂, 我们需要先来实际的代码进行演示。

下面的for循环中,图形设备中不会出现图片,并且test.pdf打开的时候会显示图形损坏。

library(meme)
u <- system.file("angry8.jpg", package="meme")

for ( i in 1:10){
  meme(u, "code", "all the things!")
}

# 图片输出到新的pdf中
pdf("test.pdf")
for ( i in 1:10){
  meme(u, "code", "all the things!")
}
dev.off()

而下面的代码中,图形设备会打印图片,并且test2.pdf能出现图片。

for ( i in 1:10){
  p <- meme(u, "code", "all the things!")
  print(p)
}
# 图片输出到新的pdf中
pdf("test2.pdf")
for ( i in 1:10){
  p <- meme(u, "code", "all the things!")
  print(p)
}
dev.off()

为什么要在for循环里要用到print才行呢?

我们在R的控制台(console)运行meme时,实际上R会给你调用对应print函数答应。而在for循环中,它不会调用print。因此你必须要显示的调用print才行。

In a loop, automatic printing is turned off, as it is inside a function

参考: https://stackoverflow.com/questions/4716152/why-do-r-objects-not-print-in-a-function-or-a-for-loop

5. 为什么meme对象能够被ggimagecowplot识别?

Y叔说的马甲其实就是指meme继承了recordedplot,不过现在版本的cowplot似乎搞不定

cowplot::plot_grid(p, p, ncol=1, labels = c("A", "B"))
# 报错如下
Error in value[[3L]](cond) : 
  invalid "recordedplot": Incompatible graphics state
In addition: Warning messages:
1: In restoreRecordedPlot(x, reloadPkgs) :
  snapshot recorded in different R version (pre 3.3.0)
2: In doTryCatch(return(expr), name, parentenv, handler) :
  snapshot recorded with different graphics engine version (pre 11 - this is version 12)

而为什么ggimage能够识别呢?ggimage是创建了一个专门的geom_image图层,为此Y叔利用ggproto,基于grid系统创造了一个GeomImage 类。这个图层就是用来绘制图片。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容