使用ggplot2绘制分面图形

浏览: 2413

在之前的一系列ggplot2绘图中都没有涉及到关于分面的操作,分面是数据可视化最实用的技术之一,通过facet_grid()和facet_wrap()函数将分组数据横向或纵向或横纵向排列,这样更有助于图形之间的比较。

上面提到facet_grid()和facet_wrap()函数可以实现可视化的分面,具体两种之间有什么区别呢?先上几幅图,通过形象的对比,就能记住两者之间的差异和用法。

一、绘制分面图

```{r}

library(ggplot2)

#创建模拟数据集

set.seed(1234)

M <- c('一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月')

Month <- rep(M, each = 5)

Region <- rep(c('East','South','West','North','Center'), times = 12)

Amount <- round(runif(n = 60, min = 500, max = 5000))

df <- data.frame(Month = Month, Region = Region, Amount = Amount)

```

首先用facet_grid()函数绘制横向或纵向分面图:

```{r}

#绘制横向的分面图

ggplot(data = df, mapping = aes(x = Region, y = Amount, fill = Region)) + geom_bar(stat = 'identity') + facet_grid(. ~ Month) + theme(axis.text.x = element_blank(), axis.ticks.x = element_blank())

```


这样一幅横向分面的条形图就绘制成功了,下面在看看纵向分面图该如何绘制?

```{r}

#绘制纵向的分面图

ggplot(data = df, mapping = aes(x = Region, y = Amount, fill = Region)) + geom_bar(stat = 'identity') + facet_grid(Month ~ .) + theme(axis.text.x = element_blank(), axis.ticks.x = element_blank())

```


图形很难看,我们从新构建一组数据以绘制纵向的分面图:

```{r}

set.seed(1234)

Year <- rep(seq(from = 2001, to = 2015),times = 4)

Type <- rep(c('A','B','C','D'), each = 15)

Value <- round(runif(60, min = 10, max = 100))

df2 <- data.frame(Year = Year, Type = Type, Value = Value)

#绘制纵向的分面图

ggplot(data = df2, mapping = aes(x = factor(Year), y = Value, group = 1)) + geom_line(colour = 'blue') + xlab('Year') + facet_grid(Type ~ .)




我们按照facet_grid()函数的语法,使用facet_wrap()函数绘制分面图

```{r}

#绘制横向的分面图

ggplot(data = df, mapping = aes(x = Region, y = Amount, fill = Region)) + geom_bar(stat = 'identity') + facet_wrap(.~ Month) + theme(axis.text.x = element_blank(), axis.ticks.x = element_blank())

```

报错了!显示错误内容为:分面中至少包含一个分层变量。经查帮助,facet_wrap()函数的语法不能写成.~ Month格式!于是改成下方的格式:

```{r}

ggplot(data = df, mapping = aes(x = Region, y = Amount, fill = Region)) + geom_bar(stat = 'identity') + facet_wrap(~ Month) + theme(axis.text.x = element_blank(), axis.ticks.x = element_blank())

```

运行成功!接下来我们看看纵向的分面图:

```{r}

#绘制纵向的分面图

ggplot(data = df, mapping = aes(x = Region, y = Amount, fill = Region)) + geom_bar(stat = 'identity') + facet_wrap(Month ~) + theme(axis.text.x = element_blank(), axis.ticks.x = element_blank())

```

OMG!!又一次报错!报错内容为:语法中存在错误的')'。查看帮助后发现:使用facet_wrap()函数不能使用Month ~语法,只能是类似于~a + b或('a','b')的形式。

经过了摸打滚爬,我们应该发现facet_grid()函数和facet_wrap()函数的区别了吧,下面总结一下:

1)facet_grid()函数会严格按照用户指定的方向分面,即横向分面必须是.~x的格式,纵向分面必须是y.~的格式,当然也可以y~x表示纵横两个维度的方向进行分面绘图;facet_wrap()函数不存在横向或纵向或横纵向的分面,其实他就像按照从左到右,从上到下的顺序摆放每一个分面图

2)语法上有显著的区别,facet_grid()函数必须是y~.或.~x或y~x的格式,而facet_wrap()函数只能是~x的格式,与之等价的是加引号的分面变量名称,即'x'。

3)上面的图形中,没有展现出来,其实facet_wrap()函数可以自由排版分面行方向的个数和列方向的个数,通过nrow=和ncol=参数实现,而facet_grid()函数只能是一根筋的下来,即要么全在行方向上,要么全在列方向上,要么就在组合方向上。下面举个facet_wrap()函数指定列数的分面图例子:

```{r}

ggplot(data = df, mapping = aes(x = Region, y = Amount, fill = Region)) + geom_bar(stat = 'identity') + facet_wrap(~Month, ncol = 3) + theme(axis.text.x = element_blank(), axis.ticks.x = element_blank())

```


上图可知,我们控制了列数为3的分面图,当然根据实际情况,也可以随意的设置其他列数或行数。

善于发现问题的朋友,一定迫不可待的问一个问题,分面图按月份绘制的话,为什么月份不是正常的“一月”到“十二月”的顺序呢?而是按照拼音的字母顺序排列。如果我想按照自定义的顺序展现我的分面图该如何操作呢?很简单,只需要从新定义字符变量的因子顺序即可:

```{r}

df$Month <- factor(df$Month, levels = c('一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月'))

#通过facet_wrap()函数绘制分面图

ggplot(data = df, mapping = aes(x = Region, y = Amount, fill = Region)) + geom_bar(stat = 'identity') + facet_wrap(~Month, ncol = 3) + theme(axis.text.x = element_blank(), axis.ticks.x = element_blank())


这下顺序正常了,而且也可以从季度的顺序发现图形展现之间的规律或特征。同样,我们也可以使用facet_grid()函数绘制分面图

```{r}

ggplot(data = df, mapping = aes(x = Region, y = Amount, fill = Region)) + geom_bar(stat = 'identity') + facet_grid(. ~ Month) + theme(axis.text.x = element_blank(), axis.ticks.x = element_blank())

```


同样也是按照指定的顺序进行排列。

二、分面图的微调

关于分面图的微调,这里就说明三项常用的微调手段,即:

非固定的坐标轴

```{r}

set.seed(1234)

height <- c(runif(100, min = 60, max = 195), runif(80, min = 45, max = 175))

weight <- 1.2*height + rnorm(180, mean = 10, sd = 20)

sex = rep(c('M','F'), times = c(100, 80))

df3 <- data.frame(sex = sex, height = height, weight = weight)

ggplot(data = df3, mapping = aes(x = height, y = weight)) + geom_point(colour = 'blue', size = 3) + facet_grid(.~sex)

```



默认情况下,分面图的纵坐标和横坐标的范围是一致的,如果我想让分面图横坐标轴的范围随实际数据大小进行调整,该如何实现?

```{r}

ggplot(data = df3, mapping = aes(x = height, y = weight)) + geom_point(colour = 'blue', size = 3) + facet_grid(.~sex, scales = 'free_x')

```



图形结果很明显,女性(F)与男性(M)的横坐标范围各不相同,男性的范围要比女性大一些这里需要强调的是,横向分面只能控制各自的x轴是否自由设定,纵向分面只能控制各自的y轴是否自由设定,纵横交错的分面可以同时设定两轴是否自由。

修改分面的文本标签

分面图形的默认情况下只显示分组变量的水平,即F和M,一个陌生人可能并不知道F和M各代表什么含义,如果能够把相应的分组变量名称也加入进来就更能提高可读性,下面通过修改一点点的脚本就能实现这样的功能:

```{r}

ggplot(data = df3, mapping = aes(x = height, y = weight)) + geom_point(colour = 'blue', size = 3) + facet_grid(.~sex, labeller = label_both)


简单吧,只需将设置labeller = label_both就可以实现功能,如果你还觉得这样做不够清晰,我还想把F和M改为Female和Male,该怎么办呢?同样很简单,只需要更改原数据中水平的标签即可。

```{r}

levels(df3$sex)[levels(df3$sex)=='F'] <- 'Female'

levels(df3$sex)[levels(df3$sex)=='M'] <- 'Male'

ggplot(data = df3, mapping = aes(x = height, y = weight)) + geom_point(colour = 'blue', size = 3) + facet_grid(.~sex, labeller = label_both)

```


修改分面标签外观

通常修改图形的外观都是通过主题theme()函数实现,毫不例外,这里也使用主题函数对分面标签外观进行修改。

```{r}

ggplot(data = df3, mapping = aes(x = height, y = weight)) + geom_point(colour = 'blue', size = 3) + facet_grid(.~sex, labeller = label_both) + theme(strip.text = element_text(colour = 'red', face = 'bold', size = rel(1.5)), strip.background = element_rect(fill = 'white', colour = 'brown', size = rel(2), linetype = 2))

``

`

其中,参数strip.text设置分面标签的颜色、大小、字体等;参数strip.background设置分面标签背景的填充色、线框色、线型等;rel()设置字体大小或线宽为原主题的倍数。

文中脚本下载链接:

https://yunpan.cn/cr4KAGsPhG8fS  访问密码 2c75

参考资料:

R语言_ggplot2:数据分析与图形艺术

R数据可视化手册

推荐 0
本文由 每天进步一点点2015 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册