### 主题(theme) #### theme函数 主题是一系列外观参数的组合,主题有一定的风格,要求个部分颜色、大小、字体、风格协调,给人一种美感。有些是具体的应用场景决定的,比如科技论文要求黑白风格的图表样式,有些期刊对字体和刻度尺有着特殊的要求,而在作报告是又会选择有颜色的图表风格。主题设置图表的整体或者综合的外观(aspect),也可以叫做图表的风格。比如线的粗细、字体大小、颜色等等。 一些参数设置是比较繁琐的,设定之后就可以作为主题固定下来,下次使用时直接应用主题就可以了。主题可以让科研人员在数据分析阶段能专注于数据而不是图形细节。 #### 用法和参数 theme_grey(base_size = 11, base_family = "") theme_gray(base_size = 11, base_family = "") theme_bw(base_size = 12, base_family = "") theme_linedraw(base_size = 12, base_family = "") theme_light(base_size = 12, base_family = "") theme_minimal(base_size = 12, base_family = "") theme_classic(base_size = 12, base_family = "") theme_dark(base_size = 12, base_family = "") theme_void(base_size = 12, base_family = "") 参数 base_size:基本文字大小,标题字体、标签字体、坐标轴字体等如果没有设定,则用基本文字大小。 base_family:基本字体。 ...: dotdotdot参数: element_line,element_rect,element_text和element_blank函数设置,使用方法参考这几个函数的参数说明即可。 text, line, rect和title是最顶层的元素,类似于抽象类,无法直接设定,可通过其子函数设置。 ```{r} x <- LETTERS[1:10] y <- abs(rnorm(10)) thm<- theme( text = element_text(color = "red", size = 16), line = element_line(color = "blue"), rect = element_rect(fill = "white")) p <- qplot(x = x, y = y, color = x, fill = x, geom = c("line", "point"), group = 1) + labs(title = "The figure title.", xlab = "Factor", ylab = "Value") + thm p + theme( panel.background = element_rect(fill = "transparent", color = "gray"), legend.key = element_rect(fill = "transparent", color = "transparent"), axis.text = element_text(color = "red")) ``` | 参数 | 内容 | 继承自 | | -------- | -------- | -------- | | line | 所有线属性 | rect | 所有矩形区域属性 | text | 所有文本相关属性 | title | 所有标题属性 | axis.title | 坐标轴标题 | text | axis.title.x | x轴属性 | axis.title | axis.title.y | y轴属性 | axis.title | axis.text | 坐标轴刻度标签属性 | text | axis.text.x | axis.text.y | axis.ticks | 坐标轴刻度线 | line | axis.ticks.x | axis.ticks.y | axis.ticks.length 刻度线长度 | axis.ticks.margin 刻度线和刻度标签之间的间距 | axis.line 坐标轴线 line | axis.line.x | axis.line.y | legend.background 图例背景 rect | legend.margin 图例边界 | legend.key 图例符号 | legend.key.size 图例符号大小 | legend.key.height 图例符号高度 | legend.key.width 图例符号宽度 | legend.text 图例文字标签 | legend.text.align 图例文字标签对齐方式 0为左齐,1为右齐 | legend.title 图例标题 text | legend.title.align 图例标题对齐方式 | legend.position 图例位置 left, right, bottom, top, 两数字向量 | legend.direction 图例排列方向 "horizontal" or "vertical" | legend.justification | 居中方式 | center或两数字向量 | legend.box | 多图例的排列方式 "horizontal" or "vertical" | legend.box.just | 多图例居中方式 | panel.background | 绘图区背景 | rect | panel.border | 绘图区边框 | rect | panel.margin | 分面绘图区之间的边距 | panel.grid | 绘图区网格线 | line | panel.grid.major | 主网格线 | panel.grid.minor | 次网格线 | panel.grid.major.x | panel.grid.major.y | panel.grid.minor.x | panel.grid.minor.y | plot.background | 整个图形的背景 | plot.title | 图形标题 | plot.margin | 图形边距 | top, right, bottom, left | strip.background | 分面标签背景 | rect | strip.text | 分面标签文本 | text | strip.text.x | strip.text.y #### ggplot2图形元素属性设置 theme_bw()函数输出可以看出主题元素及其参数和默认设置: ##### 基本对象 * line ..$ colour : chr "black" ..$ size : num 0.5 ..$ linetype: num 1 ..$ lineend : chr "butt" ..- attr(*, "class")= chr [1:2] "element_line" "element" * rect :List of 4 ..$ fill : chr "white" ..$ colour : chr "black" ..$ size : num 0.5 ..$ linetype: num 1 ..- attr(*, "class")= chr [1:2] "element_rect" "element" * text :List of 10 ..$ family : chr "" ..$ face : chr "plain" ..$ colour : chr "black" ..$ size : num 12 ..$ 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(*, "unit")= chr "pt" .. .. ..- attr(*, "valid.unit")= int 8 ..$ debug : logi FALSE ..- attr(*, "class")= chr [1:2] "element_text" "element" * axis.line :List of 4 ..$ colour : NULL ..$ size : NULL ..$ linetype: NULL ..$ lineend : NULL ..- attr(*, "class")= chr [1:2] "element_line" "element" * axis.line.x : list() ..- attr(*, "class")= chr [1:2] "element_blank" "element" * axis.line.y : list() ..- attr(*, "class")= chr [1:2] "element_blank" "element" * axis.text :List of 10 ..$ family : NULL ..$ face : NULL ..$ colour : NULL ..$ size :Class 'rel' num 0.8 ..$ hjust : NULL ..$ vjust : NULL ..$ angle : NULL ..$ lineheight: NULL ..$ margin : NULL ..$ debug : NULL ..- attr(*, "class")= chr [1:2] "element_text" "element" * axis.text.x :List of 10 ..$ family : NULL ..$ face : NULL ..$ colour : NULL ..$ size : NULL ..$ hjust : NULL ..$ vjust : num 1 ..$ angle : NULL ..$ lineheight: NULL ..$ margin :Classes 'margin', 'unit' atomic [1:4] 2.4 0 0 0 .. .. ..- attr(*, "unit")= chr "pt" .. .. ..- attr(*, "valid.unit")= int 8 ..$ debug : NULL ..- attr(*, "class")= chr [1:2] "element_text" "element" * axis.text.y :List of 10 ..$ family : NULL ..$ face : NULL ..$ colour : NULL ..$ size : NULL ..$ hjust : num 1 ..$ vjust : NULL ..$ angle : NULL ..$ lineheight: NULL ..$ margin :Classes 'margin', 'unit' atomic [1:4] 0 2.4 0 0 .. .. ..- attr(*, "unit")= chr "pt" .. .. ..- attr(*, "valid.unit")= int 8 ..$ debug : NULL ..- attr(*, "class")= chr [1:2] "element_text" "element" * axis.ticks :List of 4 ..$ colour : chr "black" ..$ size : NULL ..$ linetype: NULL ..$ lineend : NULL ..- attr(*, "class")= chr [1:2] "element_line" "element" * axis.ticks.length :Class 'unit' atomic [1:1] 3 .. ..- attr(*, "unit")= chr "pt" .. ..- attr(*, "valid.unit")= int 8 * axis.title.x :List of 10 ..$ family : NULL ..$ face : NULL ..$ colour : NULL ..$ size : NULL ..$ hjust : NULL ..$ vjust : NULL ..$ angle : NULL ..$ lineheight: NULL ..$ margin :Classes 'margin', 'unit' atomic [1:4] 4.8 0 2.4 0 .. .. ..- attr(*, "unit")= chr "pt" .. .. ..- attr(*, "valid.unit")= int 8 ..$ debug : NULL ..- attr(*, "class")= chr [1:2] "element_text" "element" * axis.title.y :List of 10 ..$ family : NULL ..$ face : NULL ..$ colour : NULL ..$ size : NULL ..$ hjust : NULL ..$ vjust : NULL ..$ angle : num 90 ..$ lineheight: NULL ..$ margin :Classes 'margin', 'unit' atomic [1:4] 0 4.8 0 2.4 .. .. ..- attr(*, "unit")= chr "pt" .. .. ..- attr(*, "valid.unit")= int 8 ..$ debug : NULL ..- attr(*, "class")= chr [1:2] "element_text" "element" * legend.background :List of 4 ..$ fill : NULL ..$ colour : logi NA ..$ size : NULL ..$ linetype: NULL ..- attr(*, "class")= chr [1:2] "element_rect" "element" * legend.margin :Class 'unit' atomic [1:1] 0.2 .. ..- attr(*, "unit")= chr "cm" .. ..- attr(*, "valid.unit")= int 1 * legend.key :List of 4 ..$ fill : NULL ..$ colour : chr "grey80" ..$ size : NULL ..$ linetype: NULL ..- attr(*, "class")= chr [1:2] "element_rect" "element" * legend.key.size :Class 'unit' atomic [1:1] 1.2 .. ..- attr(*, "unit")= chr "lines" .. ..- attr(*, "valid.unit")= int 3 * legend.key.height : NULL * legend.key.width : NULL * legend.text :List of 10 ..$ family : NULL ..$ face : NULL ..$ colour : NULL ..$ size :Class 'rel' num 0.8 ..$ hjust : NULL ..$ vjust : NULL ..$ angle : NULL ..$ lineheight: NULL ..$ margin : NULL ..$ debug : NULL ..- attr(*, "class")= chr [1:2] "element_text" "element" $ legend.text.align : NULL $ legend.title :List of 10 ..$ family : NULL ..$ face : NULL ..$ colour : NULL ..$ size : NULL ..$ hjust : num 0 ..$ vjust : NULL ..$ angle : NULL ..$ lineheight: NULL ..$ margin : NULL ..$ debug : NULL ..- attr(*, "class")= chr [1:2] "element_text" "element" $ legend.title.align : NULL $ legend.position : chr "right" $ legend.direction : NULL $ legend.justification : chr "center" $ legend.box : NULL * panel.background :List of 4 ..$ fill : chr "white" ..$ colour : logi NA ..$ size : NULL ..$ linetype: NULL ..- attr(*, "class")= chr [1:2] "element_rect" "element" * panel.border :List of 4 ..$ fill : logi NA ..$ colour : chr "grey50" ..$ size : NULL ..$ linetype: NULL ..- attr(*, "class")= chr [1:2] "element_rect" "element" * panel.grid.major :List of 4 ..$ colour : chr "grey90" ..$ size : num 0.2 ..$ linetype: NULL ..$ lineend : NULL ..- attr(*, "class")= chr [1:2] "element_line" "element" * panel.grid.minor :List of 4 ..$ colour : chr "grey98" ..$ size : num 0.5 ..$ linetype: NULL ..$ lineend : NULL ..- attr(*, "class")= chr [1:2] "element_line" "element" * panel.margin :Class 'unit' atomic [1:1] 6 .. ..- attr(*, "unit")= chr "pt" .. ..- attr(*, "valid.unit")= int 8 $ panel.margin.x : NULL $ panel.margin.y : NULL $ panel.ontop : logi FALSE * strip.background :List of 4 ..$ fill : chr "grey80" ..$ colour : chr "grey50" ..$ size : num 0.2 ..$ linetype: NULL ..- attr(*, "class")= chr [1:2] "element_rect" "element" * strip.text :List of 10 ..$ family : NULL ..$ face : NULL ..$ colour : chr "grey10" ..$ size :Class 'rel' num 0.8 ..$ hjust : NULL ..$ vjust : NULL ..$ angle : NULL ..$ lineheight: NULL ..$ margin : NULL ..$ debug : NULL ..- attr(*, "class")= chr [1:2] "element_text" "element" * strip.text.x :List of 10 ..$ family : NULL ..$ face : NULL ..$ colour : NULL ..$ size : NULL ..$ hjust : NULL ..$ vjust : NULL ..$ angle : NULL ..$ lineheight: NULL ..$ margin :Classes 'margin', 'unit' atomic [1:4] 6 0 6 0 .. .. ..- attr(*, "unit")= chr "pt" .. .. ..- attr(*, "valid.unit")= int 8 ..$ debug : NULL ..- attr(*, "class")= chr [1:2] "element_text" "element" * strip.text.y :List of 10 ..$ family : NULL ..$ face : NULL ..$ colour : NULL ..$ size : NULL ..$ hjust : NULL ..$ vjust : NULL ..$ angle : num -90 ..$ lineheight: NULL ..$ margin :Classes 'margin', 'unit' atomic [1:4] 0 6 0 6 .. .. ..- attr(*, "unit")= chr "pt" .. .. ..- attr(*, "valid.unit")= int 8 ..$ debug : NULL ..- attr(*, "class")= chr [1:2] "element_text" "element" * strip.switch.pad.grid:Class 'unit' atomic [1:1] 0.1 .. ..- attr(*, "unit")= chr "cm" .. ..- attr(*, "valid.unit")= int 1 * strip.switch.pad.wrap:Class 'unit' atomic [1:1] 0.1 .. ..- attr(*, "unit")= chr "cm" .. ..- attr(*, "valid.unit")= int 1 * plot.background :List of 4 ..$ fill : NULL ..$ colour : chr "white" ..$ size : NULL ..$ linetype: NULL ..- attr(*, "class")= chr [1:2] "element_rect" "element" * plot.title :List of 10 ..$ family : NULL ..$ face : NULL ..$ colour : NULL ..$ size :Class 'rel' num 1.2 ..$ hjust : NULL ..$ vjust : NULL ..$ angle : NULL ..$ lineheight: NULL ..$ margin :Classes 'margin', 'unit' atomic [1:4] 0 0 7.2 0 .. .. ..- attr(*, "unit")= chr "pt" .. .. ..- attr(*, "valid.unit")= int 8 ..$ debug : NULL ..- attr(*, "class")= chr [1:2] "element_text" "element" * plot.margin :Classes 'margin', 'unit' atomic [1:4] 6 6 6 6 .. ..- attr(*, "unit")= chr "pt" .. ..- attr(*, "valid.unit")= int 8 - attr(*, "class")= chr [1:2] "theme" "gg" - attr(*, "complete")= logi TRUE - attr(*, "validate")= logi TRUE #### ggplot2的预设主题。 ```{r} library(ggplot2) ``` * theme_gray:灰色主题,是ggplot2的默认主题,灰色背景,白色网格线。 ```{r} p + theme_gray() ``` * theme_bw:黑白主题,经典亮底暗字主题,帮助文档中说用于投影仪投影效果更好。 ```{r} p + theme_bw() ``` 黑白主题是其他主题的基本主题,其他主题继承了黑白主题的图形参数设置并在其基础上定制。 * theme_linedraw: 白底黑线。与黑白主题的应用场景类似,但该主题可能会绘制很细的线(小于1pt),不符合一些期刊的要求。 ```{r} p + theme_linedraw() ``` * theme_light: 类似与theme_linedraw,但是线和坐标轴是浅灰色的,网格线和坐标轴更不显眼,数据显示部分更加突出强调。 ```{r} p + theme_light() ``` * theme_dark: 与of theme_light类似, 线的尺寸相同,但使用暗背景。彩色的细线更容易看清楚。 ```{r} p + theme_dark() ``` * theme_minimal: 没有背景和注解。 ```{r} p + theme_minimal() ``` * theme_classic: 经典主题,有x轴和y轴,没有网格线。 ```{r} p + theme_classic() ``` * theme_void: 空主题 ```{r} p + theme_void() ``` #### 自定义主题 图形细节设置虽然繁琐,但是在R中可以相当简单。由于自己使用的或者杂志要求的图形外观一般都很固定,我们可以使用ggplot2的theme函数非常方便地定义自己的图形主题。坐标轴刻度朝向和统一了图形各个区域的背景颜色: ```{r} ##' A nice-looking ggplot2 theme: inward axis ticks, legend title excluded, and uniform background. ##' @title A nice-looking ggplot2 theme ##' @param ... ##' Parameters passed to theme_classic() function. ##' @param bg ##' Color string (default 'white') for user defined uniform background. ##' @return ##' ggplot2 theme object. ##' @examples ##' library(ggplot2) ##' qplot(x=carat, y=price, color=cut, data=diamonds) + theme_zg() ##' @author ZGUANG ##' @export theme_zg <- function(..., bg='white') { require(grid) theme_classic(...) + theme(rect=element_rect(fill=bg), plot.margin=unit(rep(0.5,4), 'lines'),panel.background=element_rect(fill='transparent', color='black'),panel.border=element_rect(fill='transparent', color='transparent'), panel.grid=element_blank(), axis.title = element_text(color='black', vjust=0.1), axis.ticks.length = unit(-0.4,"lines"), axis.ticks = element_line(color='black'), axis.ticks.margin = unit(0.8,"lines"), legend.title=element_blank(), legend.key=element_rect(fill='transparent', color='transparent')) } ``` 自定义的主题可以编入自己的R语言包中,方便调用。如果觉得你的主题很有代表性,可以发给ggplot2的作者H.W.,让他加到ggplot2的下一个发行版中。比如上面上面函数加入ggplot2后就可以直接调用: ```{r} p <- qplot(x = x, y = y, color = x, fill = x, geom = c("line", "point"), group = 1) + labs(title = "The figure title.", xlab = "Factor", ylab = "Value") p + theme_zg() p + theme_zg(base_size = 16, bg = "gray90")