ggplot2:精雕细琢

ggplot2:精雕细琢

本文讲述了如何修改ggplot2图表的细节。

主题

1
2
3
4
5
6
7
library(ggplot2)
library(ggthemes)
library(grid)
library(ggplot2movies)
setwd("~/Documents/notes/source/_postshttps://czxb.github.io/mr/")
theme_set(theme_grey())
(hgram <- qplot(rating, data = movies, binwidth = 1))


1
2
3
# 主题在图形创建的时候对图形无影响,在图形被绘制的时候才会影响
previous_theme <- theme_set(theme_bw())
hgram


1
hgram + previous_theme


1
2
# 永久存储初始主题
theme_set(previous_theme)

主题元素和主题函数

主题由控制图形外观的多个元素组成,见下表。有3个元素含有x和y的设置:axis.text、axis.title和strip.text。通过对水平和竖直方向元素的不同设置,我们可以控制不同方向的文本外观,这些控制元素外观的函数被成为元素函数。

表:主题元素

主题元素 类型 描述
axis.line segment 直线和坐标轴
axis.text.x text x轴标签
axis.text.y text y轴标签
axis.ticks segement 轴须标签
axis.title.x text 水平轴标题
axis.title.y text 竖直轴标题
legend.background rect 图例背景
legend.key rect 图例符号
legend.text text 图例标签
legend.title text 图例标题
panel.background rect 面板背景
panel.border rect 面板边界
panel.grid.major line 主网格线
panel.grid.minor line 次网格线
plot.background rect 整个图形背景
plot.title text 图形标题
strip.background rect 分面标签背景
strip.text.x text 水平条状文本
strip.text.y text 竖直条状文本

内置元素函数有四个基础类型:文本(text)、线条(lines)、矩形(rectangles)、空白(blank)。每个元素函数都有一系列控制外观的参数。

  1. element_text():绘制标签和标题,可控制字体的family/size/hjust/vjust/angle/lineheight。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    (hgramt <- hgram + labs(title = "这是一个直方图"))
    (hgramt2 <- hgramt + theme(plot.title = element_text(size = 20)))
    (hgramt3 <- hgramt + theme(plot.title = element_text(size = 20, colour = "red")))
    (hgramt4 <- hgramt + theme(plot.title = element_text(size = 20, hjust = 0.5)))
    (hgramt5 <- hgramt + theme(plot.title = element_text(size = 20, face = "bold")))
    (hgramt6 <- hgramt + theme(plot.title = element_text(size = 20, angle = 180)))
    library(grid)
    grid.newpage()
    pushViewport(viewport(layout = grid.layout(2, 3)))
    vp <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y)
    print(hgramt, vp = vp(1, 1))
    print(hgramt2, vp = vp(1, 2))
    print(hgramt3, vp = vp(1, 3))
    print(hgramt4, vp = vp(2, 1))
    print(hgramt5, vp = vp(2, 2))
    print(hgramt6, vp = vp(2, 3))

  1. element_line():绘制线条或线段,该元素函数可以控制colour、size、lintype:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(p1 <- hgram + theme(panel.grid.major = element_line(colour = "red")))
(p2 <- hgram + theme(panel.grid.major = element_line(size = 2)))
(p3 <- hgram + theme(panel.grid.major = element_line(linetype = "dotted")))
(p4 <- hgram + theme(axis.line = element_line()))
(p5 <- hgram + theme(axis.line = element_line(colour = "red")))
(p6 <- hgram + theme(axis.line = element_line(size = 0.5, linetype = "dashed")))
png("20181018e2.png", width = 1800, height = 1000)
grid.newpage()
pushViewport(viewport(layout = grid.layout(2, 3)))
vp <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y)
print(p1, vp = vp(1, 1))
print(p2, vp = vp(1, 2))
print(p3, vp = vp(1, 3))
print(p4, vp = vp(2, 1))
print(p5, vp = vp(2, 2))
print(p6, vp = vp(2, 3))
dev.off()

  1. element_rect()绘制主要供背景使用的矩形。可以控制填充色fill和边界border以及边界的颜色colour、size和linetype:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    (p1 <- hgram + theme(plot.background = element_rect(fill= "grey80", colour = NA)))
    (p2 <- hgram + theme(plot.background = element_rect(size = 2)))
    (p3 <- hgram + theme(plot.background = element_rect(colour = "red")))
    (p4 <- hgram + theme(panel.background = element_rect()))
    (p5 <- hgram + theme(panel.background = element_rect(colour = NA)))
    (p6 <- hgram + theme(panel.background = element_rect(linetype = "dotted")))
    png("20181018e3.png", width = 1800, height = 1000)
    grid.newpage()
    pushViewport(viewport(layout = grid.layout(2, 3)))
    vp <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y)
    print(p1, vp = vp(1, 1))
    print(p2, vp = vp(1, 2))
    print(p3, vp = vp(1, 3))
    print(p4, vp = vp(2, 1))
    print(p5, vp = vp(2, 2))
    print(p6, vp = vp(2, 3))
    dev.off()

后三个似乎没变化,可能出了BUG。

  1. element_blank():表示空主题,即对元素不分配相应的绘图空间,该函数可以用于删去我们不感兴趣的绘图元素。使用之前的colour = NAfill = NA让某些元素不可见,可达到同样的效果,单数仍占绘图空间。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    (p1 <- hgram)
    (p2 <- last_plot() + theme(panel.grid.minor = element_blank()))
    (p3 <- last_plot() + theme(panel.grid.major = element_blank()))
    (p4 <- last_plot() + theme(panel.background = element_blank()))
    (p5 <- last_plot() + theme(axis.title.x = element_blank(), axis.title.y = element_blank()))
    (p6 <- last_plot() + theme(axis.line = element_line()))
    png("20181018e4.png", width = 1800, height = 1000)
    grid.newpage()
    pushViewport(viewport(layout = grid.layout(2, 3)))
    vp <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y)
    print(p1, vp = vp(1, 1))
    print(p2, vp = vp(1, 2))
    print(p3, vp = vp(1, 3))
    print(p4, vp = vp(2, 1))
    print(p5, vp = vp(2, 2))
    print(p6, vp = vp(2, 3))
    dev.off()

使用theme_get()可得到当前的主题设置。theme()可以在一幅图中对某些元素进行局部性地修改,theme_update()可以为后面图形的绘制进行全局性地修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
old_theme <- theme_update(
plot.background = element_rect(fill = "#3366FF"),
panel.background = element_rect(fill = "#003DF5"),
axis.text.x = element_text(colour = "#CCFF33"),
axis.text.y = element_text(colour = "#CCFF33", hjust = 1),
axis.title.x = element_text(colour = "#CCFF33", face = "bold"),
axis.title.y = element_text(colour = "#CCFF33", face = "bold", angle = 90)
)

p1 <- qplot(cut, data = diamonds, geom = "bar")
p2 <- qplot(cty, hwy, data = mpg)
png("20181018e5.png", width = 1800, height = 900)
grid.newpage()
pushViewport(viewport(layout = grid.layout(1, 2)))
vp <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y)
print(p1, vp = vp(1, 1))
print(p2, vp = vp(1, 2))
dev.off()
theme_set(old_theme)

自定义标度和几何对象

标度

如果需要改变默认标度的显示方法,请重新定义或者用ggplot2中已经定义的可选方法覆盖控制相应图形属性的标度函数。该函数的命名方法通常是scale_aesthetics_continuous或者scale_aesthetics_discrete,请将函数命名中的aesthetics替换成相应的图形属性,比如fill/colour/size等等:

1
2
3
4
5
6
7
8
9
10
11
library(ggthemes)
(p1 <- qplot(mpg, wt, data = mtcars, colour = factor(cyl)) + theme_igray(base_size = 20))
scale_colour_discrete <- scale_color_brewer
(p2 <- qplot(mpg, wt, data = mtcars, colour = factor(cyl)) + theme_igray(base_size = 20))
png("20181018e6.png", width = 1800, height = 900)
grid.newpage()
pushViewport(viewport(layout = grid.layout(1, 2)))
vp <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y)
print(p1, vp = vp(1, 1))
print(p2, vp = vp(1, 2))
dev.off()

几何对象和统计变换

类似update_geom_defaults()和update_stat_defaults(),我们也可以自定义几何对象和统计变换。与其它的主题设置不同,此处设置只影响设置改变后新绘制的图形,而不是所有图形。下面的例子展示了如何改变默认颜色和将默认直方图改变成密度直方图。

1
2
3
4
5
6
7
8
9
10
11
12
13
theme_set(theme_igray(base_size = 25))
library(ggplot2movies)
update_geom_defaults("point", aes(colour = "darkblue"))
p1 <- qplot(mpg, wt, data = mtcars)
update_stat_defaults("bin", aes(y = ..density..))
p2 <- qplot(rating, data = movies, geom = "histogram", binwidth = 1)
png("20181018e7.png", width = 1800, height = 900)
grid.newpage()
pushViewport(viewport(layout = grid.layout(1, 2)))
vp <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y)
print(p1, vp = vp(1, 1))
print(p2, vp = vp(1, 2))
dev.off()

一页多图

1
2
3
4
5
6
7
8
9
10
11
12
library(grid)
(a <- qplot(date, unemploy, data = economics, geom = "line"))
(b <- qplot(uempmed, unemploy, data = economics) + geom_smooth(se = F))
(c <- qplot(uempmed, unemploy, data = economics, geom = "path"))
## 一个占据整个图形设备的视图窗口
vp1 <- viewport(width = 1, height = 1, x = 0.5, y = 0.5)
vp1 <- viewport()
## 只占了图形设备一般的宽和高的视图窗口,定位在图形的中间位置
vp2 <- viewport(width = 0.5, height = 0.5, x = 0.5, y = 0.5)
vp2 <- viewport(width = 0.5, height = 0.5)
## 一个2cm x 3cm的视图窗口,定位在图形设备的中心
vp3 <- viewport(width = unit(2, "cm"), height = unit(3, "cm"))

默认地,x和y参数控制着视图窗口的中心位置,若想调整图形位置,你需要通过just参数来控制图形放置在哪个边角。

1
2
3
4
## 在右上角的视图窗口
vp4 <- viewport(x = 1, y = 1, just = c("top", "right"))
## 在左下角
vp5 <- viewport(x = 0, y = 0, just = c("bottom", "right"))

1
2
3
4
theme_set(theme_igray(base_size = 15))
subvp <- viewport(width = 0.4, height = 0.4, x = 0.75, y = 0.35)
b
print(c, vp = subvp)

矩形网格

1
2
3
4
5
6
7
8
png("20181018e9.png", width = 1800, height = 900)
grid.newpage()
pushViewport(viewport(layout = grid.layout(2, 2)))
vp <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y)
print(a, vp = vp(1, 1:2))
print(b, vp = vp(2, 1))
print(c, vp = vp(2, 2))
dev.off()

# R

评论

程振兴

程振兴 @czxa.top
截止今天,我已经在本博客上写了659.4k个字了!

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×