R数据可视化-ggplot2的分面

分面(facet)是在一个页面上自动摆放多幅图形,这一过程先将数据划分为多个子集,然后将每个子集依次绘制到页面的不同面板中。

ggplot2提供了两种分面类型:

  • 网格分面-facet_grid:生成一个2维的面板网格,面板的行与列通过变量来定义。本质是2维的
  • 封装分面-facet_wrap:首先生成一个1维的面板条块,然后再分装到2维中。本质是1维的

网格分面-facet_grid

网格分面生成的是一个2维的面板网格,面板的行与列通过变量来定义。本质是2维的。

不进行分面

不进行分面:即不使用函数facet_grid()或使用facet_null()函数,此时得到的是单独画板。

1
2
3
4
p <- ggplot(data = diamonds, mapping = aes(x = carat, y = price))
p <- p + geom_point()
p <- p + facet_null()
p

一行多列

一行多列:纵坐标相同,用于y位置的比较。

1
2
3
4
p <- ggplot(data = diamonds, mapping = aes(x = carat, y = price))
p <- p + geom_point()
p <- p + facet_grid('. ~ cut')
p

电脑屏幕通常较宽,因此这个方向最合适数据的展示

一列多行

一列多行:横坐标轴相同,利于x位置的比较,尤其是对数据分布的比较

1
2
3
4
p <- ggplot(data = diamonds, mapping = aes(x = price))
p <- p + geom_histogram(binwidth = 30)
p <- p + facet_grid('cut ~ .')
p

多列多行

我们通常都将数目最多的变量按列排放,这样可以充分利用屏幕的宽高比。

1
2
3
4
p <- ggplot(data = diamonds, mapping = aes(x = carat, y = price))
p <- p + geom_point()
p <- p + facet_grid('cut ~ color')
p

facet_grid()函数的参数

facet_grid()函数的全部参数如下:

1
2
facet_grid(facets, margins = FALSE, scales = "fixed", space = "fixed", shrink = TRUE,
labeller = "label_value", as.table = TRUE, drop = TRUE)
  • facets:分面参数
  • margins:用于分面的包含每个变量元素所有数据的数据组
  • scales:坐标刻度的范围,可以设定四种类型:
    • fixed:表示所有小图均使用统一坐标范围
    • free:表示每个小图按照各自数据范围自由调整坐标刻度范围
    • free_x:表示可以自由调整x轴刻度范围
    • free_y:表示可以自由调整y轴刻度范围
  • space:这个参数要配合scales使用,如果为fixed(默认),所有小图的大小都一样,如果为free/free_x/free_y,小图的大小将按照坐标轴的跨度比例进行设置
  • shrinks:这个参数和坐标轴刻度有关,如果为TRUE(默认)则按统计后的数据调整刻度范围,否则按统计前的数据设定坐标
  • labeller:这个参数用来设定小图标签
  • as.table:小图排列顺序有关的选项。如果为TRUE(默认)则按表格方式排列,即最大值(指分组level值)排在表格最后即右下角,否则排在左上角
  • drop:是否丢弃没有数据的分组,如果为TRUE(默认),则空数据组不绘图

margins

我们可以用margins来绘制边际图。设定margins=TRUE可展示所有的边际图,或者margins=c("A","B"),列出你要展示的边际图的变量名称。

1
2
3
4
5
6
7
8
p <- ggplot(data = diamonds, mapping = aes(x = price))
p <- p + geom_histogram(binwidth = 30)

# 默认-左图
p + facet_grid(facets = 'cut ~ .')

# 展示所有的边际图(margins = TRUE)-右图
p + facet_grid(facets = 'cut ~ .', margins = TRUE)

scales

固定标度可以让我们在相同的基准上对子集进行比较,观察在哪些地方各子集有相似的总体模式。而自由标度可以帮助我们发现更多细节,它在展示不同量纲的时间序列时非常有用。

1
2
3
4
5
6
7
8
p <- ggplot(data = diamonds, mapping = aes(x = price))
p <- p + geom_histogram(binwidth = 30)

# 每个分面中固定标度即横纵坐标范围相同-左图
p + facet_grid(facets = 'cut ~ .', scales = 'fixed')

# 自由标度即横纵坐标范围可变-右图
p + facet_grid(facets = 'cut ~ .', scales = 'free')

space

1
2
3
4
5
6
7
8
p <- ggplot(data = diamonds, mapping = aes(x = price))
p <- p + geom_histogram(binwidth = 30)

# 每个分面中固定标度即横纵坐标范围相同-左图
p + facet_grid(facets = 'cut ~ .', scales = 'fixed', space = 'fixed')

# space设置为free时,每列的宽度与该列的标度范围成比例-右图
p + facet_grid(facets = 'cut ~ .', scales = 'free', space = 'free')

封装分面-facet_wrap

封装分面首先生成一个1维的面板条块,然后再分装到2维中。本质是1维的

facet_wrap()函数的参数

facet_wrap()函数的全部参数如下:

1
2
facet_wrap(facets, nrow = NULL, ncol = NULL, scales = "fixed",
shrink = TRUE, as.table = TRUE, drop = TRUE)

前面已经介绍过网格分面的参数,这里的封装分面的参数也是类似的,下面介绍不同的几个参数:

  • nrow:绘制图形的行数
  • ncol:绘制图形的列数,一般nrow/ncol只设定一个即可

默认设置

1
2
3
4
5
# 默认设置
p <- ggplot(data = diamonds, mapping = aes(x = carat, y = price))
p <- p + geom_point()
p <- p + facet_wrap(~ color)
p

设置列

1
2
3
4
5
# 通过ncol=2设置为两列
p <- ggplot(data = diamonds, mapping = aes(x = carat, y = price))
p <- p + geom_point()
p <- p + facet_wrap(~ color, ncol = 2)
p

分面与分组对比

这两种绘图技巧都有相应的优缺点。

在分面图形中,每个组别都在单独的面板中,相隔较远,组间无重叠。因此组与组之间重叠严重时,分面图形有一定的好处。不过这也会导致组间的细微差别难以被发现。使用图形属性区分各组时,各组将会离得很近甚至可能重叠,不过细微得差别将会容易被发现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
library(gridExtra)

# 分组-左上
p1 <- ggplot(data = diamonds, mapping = aes(x = carat, y = price, colour = cut))
p1 <- p1 + geom_point()

# 分面-右上
p2 <- ggplot(data = diamonds, mapping = aes(x = carat, y = price, colour = cut))
p2 <- p2 + geom_point()
p2 <- p2 + facet_grid('. ~ cut')

# 分组-只显示回归线-左下
p3 <- ggplot(data = diamonds, mapping = aes(x = carat, y = price, colour = cut))
p3 <- p3 + geom_smooth(method = lm, se = F, fullrange = T)

# 分面-只显示回归线-右下
p4 <- ggplot(data = diamonds, mapping = aes(x = carat, y = price, colour = cut))
p4 <- p4 + geom_smooth(method = lm, se = F, fullrange = T)
p4 <- p4 + facet_grid('. ~ cut')

p <- grid.arrange(p1,p2,p3,p4,ncol=2)

我们可以使用color或者fill图形属性来为分面条形图上色

在散点图中,仅使用颜色区分各组,我们可能还没注意到图形重叠了,但是回归线却可以让我们看到Ideal、Premium、Good、Very Good被分组在一起,与Fair组相距甚远。

分面与并列对比

分面可绘制出与图形并列类似得图形效果。

1
2
3
4
5
6
7
8
9
10
11
12
library(gridExtra)

# 并列-左图
p1 <- ggplot(data = diamonds, mapping = aes(x = color, fill = cut))
p1 <- p1 + geom_bar()

# 分面-右图
p2 <- ggplot(data = diamonds, mapping = aes(x = color, fill = cut))
p2 <- p2 + geom_bar()
p2 <- p2 + facet_grid('. ~ cut')

grid.arrange(p1,p2,ncol=2)

我们可以使用color或者fill图形属性来为分面条形图上色

参考


----------- 本文结束啦感谢您阅读 -----------

赞赏一杯咖啡