前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ggplot2学习笔记之——ggplot2主题调整系统

ggplot2学习笔记之——ggplot2主题调整系统

作者头像
数据小磨坊
发布2018-04-16 10:55:22
1.1K0
发布2018-04-16 10:55:22
举报
文章被收录于专栏:数据小魔方数据小魔方

ggplot2绘图系统拥有庞大、健全的图形美化系统,这一套图形美化依赖于图例调整系统、标度调整系统、标签调整系统、主题调整系统以及分面系统。

本节仅从主题调整系统来浅析ggplot2是如何实现脱离数据层面的信息,单独实现主题调整系统的。

从大的层面上来说,ggplot2的主题系统知识主要分为三个层面:

一、主题调整函数: 二、元素调整函数: 三、元素调整参数:

主题调整函数很好理解,就是用于封装主题的函数,可以是预设主题(系统默认的主题函数)、也可以是第三方接口包提供的定制主题(如ggthemes包、ggtech包、ggsci包等)、或者是自己通过主题调整函数自定义的主题。

ggplot2的默认主题是theme_gray(),也即你在绘制图形的时候,即便不指定主题,默认调用的也是这款主题。

你可以通过theme_get()函数获取当前主题的所有参数配置列表,当然直接运行theme_gray()函数【这里要注意运行theme_gray()和运行theme_gray获取的结果是不一样的,执行theme_gray()是运行一个函数,返回的是一个列表格式的主题参数配置对象,而直接运行theme_gray则是打印出了theme_gray函数本身的语句信息,这一点儿需要区分清楚,函数本身与函数对象输出结果是截然不同的两个对象】时,同样可以得到这主题的参数配置列表。

代码语言:javascript
复制
p <- ggplot(mtcars) + geom_point(aes(x = wt, y = mpg,
     colour = factor(gear))) + facet_wrap(~am)
p + theme_gray() # the default

theme_set(new) 函数很特别,它接受一个新定义的主题同时,会将系统系统默认主题静默返回,这样你在使用时需将这个函数指定为一个临时对象,以便自定义主题使用之后,方便回复系统之前的默认主题。(如果不存储反悔的旧主题的话,那么系统就无法恢复到当默认主题了【当然重新启动系统就恢复了】)。

代码语言:javascript
复制
p <- ggplot(mtcars, aes(mpg, wt)) +
  geom_point();p
代码语言:javascript
复制
old <- theme_set(theme_bw());p
代码语言:javascript
复制
theme_set(old);p

theme_update()函数和theme_replace()函数是一对相爱相杀的函数,两者存在着微妙的关系,也是涉猎不神的初学者最容易困惑的两个主题函数。

这里澄清一下(也是参考ggplot2官网上的原文解释),theme_update()与theme_replace()函数都可以起到修改主题的作用,但是不同的是二者在修改主题的时候作用方式不同。

theme_update()函数是一种增量更新,也即在默认主题的基础上,对比与theme_update()函数内部各个主题参数之间的差异,有差异的以新增的为主,无差异的则保持不变。

而theme_replace()函数则更为霸道,它是一种全量更新,即在默认主题的基础上,比对与theme_replace()函数内部主题参数之间的差异,有差异则以后者为准,但是theme_replace()函数内部没有生命的所有参数(也即你未指定的那些元素参数)都会被初始化为NULL,也即只应用你显式声明的那些自定义参数,为生命的都会被清空,较为霸道。

这两者解释清楚了,那么下一个问题又来了,看到之前写过的代码,有时候我使用主题函数用的 + theme(),有时候则用的是 %+replace% theme(),这两者又有什么区别呢,这两者与上面提到过的theme_update()与theme_replace()函数是否有关联呢。

其实还真的有关联,这里直接说结论。

theme_update() 等价于 theme_gray() + theme(),theme()函数内部的参数会替换theme_gray()内部的同名参数,未声明的则保持不变。 theme_replace() 等价于 theme_gray() %+replace% theme(),theme()函数内部的参数会替换theme_gray()内部的同名参数,未声明的参数全部初始化为NULL。

所以你也可以理解为,theme_update()直接作用于当前主题,theme_replace()则是仅仅使用显式声明的主题元素外,所有未声明的都清空。

这便是这两组函数的区别于关联,通常来讲,用哪一组是习惯问题,单也要看场景,你是需要所有元素都重新修改,还是只要修改其中某几个元素。

代码语言:javascript
复制
add_el <- theme_grey() +
  theme(text = element_text(family = "Times"))

add_el$text
#> List of 11
#>  $ family       : chr "Times"
#>  $ face         : chr "plain"
#>  $ colour       : chr "black"
#>  $ size         : num 11
#>  $ hjust        : num 0.5
#>  $ vjust        : num 0.5
#>  $ angle        : num 0
#>  $ lineheight   : num 0.9
#>  $ margin       :Classes 'margin', 'unit'  
atomic [1:4] 0 0 0 0#>   .. ..- attr(*, "valid.unit")= int 8
#>   .. ..- attr(*, "unit")= chr "pt"
#>  $ debug        : logi FALSE
#>  $ inherit.blank: logi FALSE
#>  - attr(*, "class")= chr [1:2] "element_text" "element"
代码语言:javascript
复制
rep_el <- theme_grey() %+replace%
  theme(text = element_text(family = "Times"))

rep_el$text
#> List of 11
#>  $ family       : chr "Times"
#>  $ face         : NULL
#>  $ colour       : NULL
#>  $ size         : NULL
#>  $ hjust        : NULL
#>  $ vjust        : NULL
#>  $ angle        : NULL
#>  $ lineheight   : NULL
#>  $ margin       : NULL
#>  $ debug        : NULL
#>  $ inherit.blank: logi FALSE
#>  - attr(*, "class")= chr [1:2] "element_text" "element"

ggplot2的主题元素函数主要有四大类(其实是三大类):

代码语言:javascript
复制
element_text()
element_rect()
element_line()
element_blank()

这些函数很好理解,分别是文本类型、矩形区域、线条类型等。最后一个只是为了方便清空某类主题元素而设计的。

这三类主题元素函数将所有的ggplot2图形主题元素全部都抽象进去了,而且做了严格的子孙继承关系链与权限控制范围。

从text、rect、line这三个全局主题元素到之后的各个主题模块的各类text、rect、line及其衍生主题,都遵循这种子孙继承关系。

比如你制定了text = element_text(family= ,size = ,angle = , colour = )吗,那么所有的模块涉及到主题文本元素的都会强制遵守这些参数,如果仅仅是为了修改某一个模块的局部文本元素,你绝对不可以设置这么高级别的文本调整函数,而是直接定位到局部主题文本调整函数进行对应的参数设置即可,比如 Axis.title.y = element_text(family= ,size = ,angle = , colour = ),类似这种控制权限,rect和line都是遵从的。

整个继承关系链可以参考这个图。

这些参数在ggplot2的官方文档上都写的清清楚楚、明明白白。

除了主题元素调整 函数之外,第三块内容当然就是这些主题元素调整函数内部的元素参数啦~

这些元素参数都是高度抽象化、统一化的,也意味着很多都是通用的,与美学映射内的参数看齐的。

代码语言:javascript
复制
--------------
element_text()
----------------------------------------------------
Argument    Description               Default Value
-----------------------------------------------------
family      font family               ""
face        font  face                "plain"
colour      font color                "black"
size        font size(pts)            10
hjust       horizontal justification  0.5
vjust       vertical justification    0.5
angle       text angle                0
lineheight  line height               1.1

--------------
element_line()
-----------------------------------------------------
Argument    Description               Default Value
-------------------------------------------------------
colour      line color                "black"
size        line thickness            0.5
linetype    type of line              1

--------------
element_rect()
---------------------------------------------------
Argument    Description               Default Value
---------------------------------------------------
fill        fill color                NA(none)
colour      border color              "black"
size        thickness of border line  0.5
linetype    type of border line       1(solid)
-----------------------------------------------------

讲了这么多,一个案例来复习下:

代码语言:javascript
复制
library("ggplot2")
library("reshape2")
library("ggthemes")
library("magrittr")

mydata <- data.frame(
  Name = c("苹果","谷歌","脸书","亚马逊","腾讯"),
  Company = c("Apple","Google","Facebook","Amozon","Tencent"),
  Sale2013 = c(5000,3500,2300,2100,3100),
  Sale2014 = c(5050,3800,2900,2500,3300),
  Sale2015 = c(5050,3800,2900,2500,3300),
  Sale2016 = c(5050,3800,2900,2500,3300)
  )  %>% melt(
  id.vars=c("Name","Company"),
  variable.name="Year",
  value.name="Sale"
  )
代码语言:javascript
复制
#默认主题
ggplot(mydata,aes(Company,Sale,fill=Year))+
  geom_bar(stat="identity")
#默认主题(theme_gray())

ggplot(mydata,aes(Company,Sale,fill=Year))+
  geom_bar(stat="identity")+
  theme_gray()

预设主题1

代码语言:javascript
复制
ggplot(mydata,aes(Company,Sale,fill=Year))+
  geom_bar(stat="identity") +
theme_bw()

自定义封装主题函数:

代码语言:javascript
复制
###方法一:

windowsFonts( myFont = windowsFont("微软雅黑"))
theme_xmf <- theme_replace(
  plot.title       =  element_text(size = 20,family="myFont",hjust = 0,lineheight = 2),
  plot.subtitle    =  element_text(size = 15,family="myFont",hjust = 0,lineheight = 2),
  plot.caption     =  element_text(size = 18,family="myFont",hjust = 0,lineheight = 2),
  plot.background  =  element_rect( fill = '#efefef',size = 0.8 ,linetype = 3, color = 'grey'),
  plot.margin      =  margin(10,5,10,5,unit="pt"),
  legend.position  =  "top" ,
  panel.border     =  element_blank(),
  panel.background =  element_rect(fill = '#d4dee7',size = 2 ,linetype = 3, color = 'grey'),
  panel.grid.major =  element_line(linetype = "dashed"),
  panel.grid.minor =  element_blank(),
  axis.line        =  element_line(size = 1.2 , colour = 'black',linetype  = 1),
  axis.text        =  element_text(size=10,colour="#003087",family="myFont"),
  legend.text      =  element_text(size=9,colour="#003087",family="myFont"),
  legend.key       =  element_blank()
)

ggplot(mydata,aes(Company,Sale,fill=Year))+
  geom_bar(stat="identity") +
  scale_fill_brewer(palette="Blues") +
  guides(fill = guide_legend(reverse = TRUE)) +
  labs(
    title = '这里是主标题',
    subtitle = '这里是副标题',
    caption = '这里是备注'
  ) +  theme_xmf

方法2

代码语言:javascript
复制
theme_manual <- function(){
  theme_get() %+replace% theme(
    plot.title      = element_text(size = 20,family="myFont",hjust = 0,lineheight = 2),
    plot.subtitle   = element_text(size = 15,family="myFont",hjust = 0,lineheight = 2),
    plot.caption    = element_text(size = 18,family="myFont",hjust = 0,lineheight = 2),
    plot.background = element_rect(fill = '#efefef',size = 0.8 ,linetype = 3, color = 'grey'),
    plot.margin     = margin(10,5,10,5,unit="pt"),
    legend.position="top",
    panel.border=element_blank(),
    panel.background = element_rect(fill = '#d4dee7',size = 2 ,linetype = 3, color = 'grey'),
    panel.grid.major=element_line(linetype="dashed"),
    panel.grid.minor=element_blank(),
    axis.line = element_line(size = 1.2 , colour = 'black',linetype  = 1),
    axis.text=element_text(size=10,colour="#003087",family="myFont"),
    legend.text=element_text(size=9,colour="#003087",family="myFont"),
    legend.key=element_blank()
  )
} 

ggplot(mydata,aes(Company,Sale,fill=Year))+
  geom_bar(stat="identity") +
  scale_fill_brewer(palette="Blues") +
  guides(fill = guide_legend(reverse = TRUE)) +
  labs(
    title = '这里是主标题',
    subtitle = '这里是副标题',
    caption = '这里是备注'
  ) + theme_manual()

是不是要比原生的主题要更加简洁、专业一些呢~

一句老套的话,要想学到真功夫,要下定决心去啃源文档~

http://ggplot2.tidyverse.org/reference/

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

本文分享自 数据小魔方 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 方法2
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档