本期内容:
- facet_wrap(一维面板)
- facet_grid(二维面板)
如何将一个数据的多个子数据集同时展示在一个页面?本期我们来学习ggplot2中的分面功能。老规矩,依然依然依然还是iris这个数据,此次在此数据基础上随机生成两个新变量Class和Group,如下,Class列包含1-3三种类型,Group列包含A和B两种类型(将Group设置为因子型,注意这里我们将levels设置为了先B再到A):
DT <- iris
set.seed(8)
DT$Class <- sample(1:3, nrow(iris), replace = T)
set.seed(88)
DT$Group <- sample(LETTERS[1:2], nrow(iris), replace = T)
DT$Group <- factor(DT$Group, levels = c("B", "A")) # 转为因子型
head(DT, 20)
请出这个老演员,依然以它为初始图:
library(ggplot2)
p <- ggplot(data = DT, aes(x = Sepal.Length, y = Sepal.Width)) +
geom_point(aes(color = Petal.Length, size = Petal.Width, shape = Species)) +
scale_color_gradient(low = "#f0cf61", high = "#371722") +
scale_size_continuous(range = c(1, 4)) +
theme_classic() +
labs(x = "Sepal Length", y = "Sepal Width", title = "Iris Sepal") +
theme(plot.title = element_text(size = 15, face = "bold", hjust = 0.5),
axis.title = element_text(face = "bold"),
legend.title = element_text(face = "bold"),
axis.text = element_text(size = 13),
legend.text = element_text(size = 12))
p
facet_wrap(一维面板)
首先我们按照Species的分类来生成一幅分面图:
p + facet_wrap(facets = vars(Species))
可以看到初始图中的点按照Species拆分为了三个子图,以上每个子图对应顶部标签所示分组。如果想再叠加一层其他变量,比如Group可以如下:
p + facet_wrap(facets = vars(Species, Group))
它还有另外两种写法:
p + facet_wrap(facets = c("Species", "Group"))
p + facet_wrap(facets = ~ Species + Group)
上图中,比如第一个子图中的每个点就代表Species为setosa同时Group为B的鸢尾花萼片的长和宽。
分面标签调整
调整输入列名的顺序即可修改分面标签的顺序(另两种写法同理):
p + facet_wrap(facets = ~ Group + Species)
分面标签默认直接显示分面变量的值,也可以简单加上变量的名称,如:
p + facet_wrap(facets = ~ Group + Species, labeller = "label_both")
# 或
p + facet_wrap(facets = \~ Group + Species, labeller = label_both)
此处label_both为预先定义好的函数,另外的函数还有:(具体详见labellers帮助文档)
label_value
label_context
label_parsed
label_wrap_gen
我们还可以自定义函数,比如我们定义一个对输入值截取前两个字母的函数,然后使用labeller函数转换为参数传递给labeller选项:
SUB <- function(x) {
substr(x, 1, 2)
}
p + facet_wrap(facets = ~ Group + Species,
labeller = labeller(Species = SUB))
或者直接指定替换内容:
Group2 <- c(B = "Group: B", A = "Group: A")
Species2 <- c(setosa = "SE", versicolor = "VE", virginica = "VI")
print(Group2)
print(Species2)
p + facet_wrap(facets = ~ Group + Species,
labeller = labeller(Group = Group2,
Species = Species2))
用strip.position函数可以调整分面标签的位置,如下调至右方:
p + facet_wrap(facets = ~ Group + Species, strip.position = "right")
固定行/列数
此外我们还可以固定分面展示的行数,如下,让它排成一行:
p + facet_wrap(facets = ~ Group + Species, nrow = 1)
或者列数,如下排成两列:
p + facet_wrap(facets = ~ Group + Species, ncol = 2)
分面展示顺序
在以上的图片中,沿水平方向(从左往右),从上往下,我们可以看到子图展示的顺序为:
B 👉 A
setosa 👉 versicolor 👉 virginica
这是因为我们在设置facets时,设置了先Group后Species,因此会先按Group再按Species来排序。另外,在ggplot2绘图中对于因子变量的绘图,顺序会默认按照其levels设置的顺序。这两个变量的levels顺序分别为以上顺序:
levels(DT$Species)
levels(DT$Group)
在facet_wrap中的dir参数默认值为h (水平方向),
as.table参数默认值为TRUE,因此它会按照我们日常看表格的习惯来从上至下,从左至右排布:
所以要想按照垂直方向摆放图片,只需:
p + facet_wrap(facets = ~ Group + Species, ncol = 2, dir = "v")
而当as.table参数默认值为FALSE时,则是按照绘图的逻辑,从下到上摆放:
p + facet_wrap(facets = ~ Group + Species, ncol = 2, as.table = F)
调整坐标轴显示范围
以上我们可以看到所有子图的坐标轴是固定的,如果想要坐标轴根据每个子图中的实际数值范围来决定,我们可以用scales选项设置:fixed(默认,X和Y轴都固定);free_x(X轴自由,固定Y轴);free_y(Y轴自由,固定X轴);free(X和Y轴都自由)。如:
p + facet_wrap(facets = ~ Group + Species, ncol = 2, scales = "free_x")
p + facet_wrap(facets = ~ Group + Species, ncol = 2, scales = "free_y")
p + facet_wrap(facets = ~ Group + Species, ncol = 2, scales = "free")
facet_grid(二维面板)
通过以上内容我们可以发现facet_wrap只有一个维度,它的排布没有行列的概念,只是根据子集作图然后按顺序排布。接下来我们了解一下二维排布的面板,如下我们设置以Species来按行分面:
p + facet_grid(rows = vars(Species))
# 或其它两种写法(同facet_wrap)
p + facet_grid(rows = "Species")
p + facet_grid(Species ~ .)
或者按列分面:
p + facet_grid(. ~ Species)
或者以Group按行,Species按列分面:
p + facet_grid(Group ~ Species)
以上每个子图,比如左上第一个,即对应Species为setosa且Group为B的数据作的图,把Class变量也加进来:
p + facet_grid(Group + Class ~ Species)
调整坐标轴的显示范围的方式和facet_warp一致:
p + facet_grid(Group + Class ~ Species, scales = "free")
此外facet_grid还提供space选项,来根据坐标轴范围自由调整各个子图大小,同样也是:fixed(默认,X和Y轴都固定);free_x(X轴自由,固定Y轴);free_y(Y轴自由,固定X轴);free(X和Y轴都自由)。如下XY轴都自由调整:
p + facet_grid(Group + Class ~ Species, scales = "free", space = "free")
最后,还可以使用margin选项添加一个额外的分面来显示当前分面行或列的所有数据:
p + facet_grid(Group ~ Species, scales = "free", space = "free",
margins = T)
如果只想显示其中一个分面的所有数据,可以直接指定分面的变量名:
p + facet_grid(Group ~ Species, scales = "free", space = "free",
margins = "Species")
labeller选项设置分面标签和as.table设置摆放顺序的方法和facet_wrap中的一致,在此不再进行赘述。
最后
- 感谢支持,希望对您有帮助!
- 有不足的地方欢迎指正!
- 关注我们,及时获取更多干货!