R语言图表美化——巧用分面表达优化图表布局,做出堪比杂志级视觉体验的商务图表

图表的优化布局在Excel中一直都是个大难题,难在Excel软件固有的限制。

特别是在制作多序列多分类图表的时候,放在一个图中显得序列过于拥挤,影响视觉效果,做出分面表达又耗时费力,需要掌握诸多技巧,(版式设计呀、单元格锚定呀等等、照相机呀什么的)是在是有心无力。

但是像R语言这样依靠图形语法来控制的作图形式,却不存在这样的问题。

今天跟大家分享如何在R语言中巧用分面表达来优化多系列多分类图表的版式布局!

其实这一篇在不久前曾经发过的,当时还处于摸索阶段,写的很粗糙,今天重发一遍,所有的代码和图表都是优化过的,不仔细观察,还真看不出来,仔细对比一下就能发现了!

我是分割线~


当数据序列比较多的时候,特别是超过四个以后,还用堆积柱形图(条形图)、或者簇状柱形图的话,图表必然会因为系列太多而受到挤压或者变形,整体就会不协调、不美观。

还有ggplot不支持次坐标轴功能,它的作图思维基本源于塔夫脱的可视化理念,而且作者个人的审美也比较抵触次坐标轴,但是他留给大家解决多序列图表的方案是——图形分面

以下仅以常用的柱形图、条形图为例进行讲解(所有的图形对象几乎都支持分面)

构造作图数据集:

1
2
3
4
5
6
data<-data.frame(Name = c("苹果","谷歌","脸书","亚马逊","腾讯"),
Conpany = c("Apple","Google","Facebook","Amozon","Tencent"),
Sale2013 = c(5000,3500,2300,2100,3100),
Sale2014 = c(5050,3800,2900,2500,3300),
Sale2015 = c(5050,3800,2900,2500,3300),
Sale2016 = c(5050,3800,2900,2500,3300))

数据重塑(宽转长):

1
mydata<-melt(mydata,id.vars="Conpany",variable.name="Year",value.name="Sale")

作图函数:

默认输出图表:

1
2
ggplot(mydata,aes(Conpany,Sale,fill=Year))+
geom_bar(stat="identity",position="dodge")

默认图表的配色确实挺难看的,这里我使用华尔街日报、经济学人的主题、及配色模板进行适度美化。

华尔街日报:

1
2
3
4
5
6
7
ggplot(mydata,aes(Conpany,Sale,fill=Year))+
geom_bar(stat="identity",position="dodge")+
theme_wsj()+
scale_fill_wsj("rgby", "")+
guides(fill=guide_legend(title=NULL))+
ggtitle("The Financial Performance of Five Giant")+
theme(axis.title = element_blank())

经济学人

1
2
3
4
5
6
7
ggplot(mydata,aes(Conpany,Sale,fill=Year))+
geom_bar(stat="identity",position="dodge")+
theme_economist(base_size=14)+
scale_fill_economist()+
guides(fill=guide_legend(title=NULL))+
ggtitle("The Financial Performance of Five Giant")+
theme(axis.title = element_blank())

以上是我们使用传统的方法通过将颜色映射到不同类别的年度收入变量上,达到了区分效果,可是这样终究不是办法,五个序列实在是有点多,已经让然有点儿眼花缭乱了,如果有8个序列、10个序列呢,那又该怎么办呢~

下面跟大家分享其中一种比较有效的解决办法——通过分面表达解决多序列图表呈现问题

横排分面:

柱形分面(横排):

1
2
3
4
5
6
7
8
ggplot(mydata,aes(Conpany,Sale,fill=Year))+
geom_bar(stat="identity",position="dodge")+
theme_wsj()+
scale_fill_wsj("rgby", "")+
guides(fill=guide_legend(title=NULL))+
ggtitle("The Financial Performance of Five Giant")+
theme(axis.title = element_blank(),legend.position='none')+
facet_grid(.~Year)

1
2
3
4
5
6
7
8
9
10
11
12
ggplot(mydata,aes(Conpany,Sale,fill=Year))+
geom_bar(stat="identity",position="dodge")+
facet_grid(.~Year)+
theme_economist(base_size=14)+
scale_fill_economist()+
guides(fill=guide_legend(title=NULL))+
ggtitle("The Financial Performance of Five Giant")+
theme(
axis.title = element_blank(),
legend.position='none',
axis.text.x=element_text(size=7.5)
)

条形分面(横排):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ggplot(mydata,aes(Conpany,Sale,fill=Year))+
geom_bar(stat="identity",position="dodge")+
theme_wsj()+
scale_fill_wsj("rgby", "")+
guides(fill=guide_legend(title=NULL))+
facet_grid(.~Year)+
coord_flip()+
ggtitle("The Financial Performance of Five Giant")+
theme(
axis.title = element_blank(),
legend.position='none',
axis.text.y=element_text(size=10),
axis.text.x=element_text(size=7.5),
axis.ticks.x=element_blank(),
axis.ticks.y=element_line(),
axis.ticks.length=unit(0.5,'cm'),
axis.line.y=element_line(),
axis.line.x=element_blank(),
panel.grid.major.x=element_line(linetype="dashed",colour="grey60"),
panel.grid.major.y=element_blank()
)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ggplot(mydata,aes(Conpany,Sale,fill=Year))+
geom_bar(stat="identity",position="dodge")+
theme_economist(base_size=14)+
facet_grid(.~Year)+
coord_flip()+
scale_fill_economist()+
theme(axis.ticks.length=unit(0.5,'cm'))+
guides(fill=guide_legend(title=NULL))+
ggtitle("The Financial Performance of Five Giant")+
theme(
axis.title = element_blank(),
legend.position='none',
axis.text.y=element_text(size=10),
axis.text.x=element_text(size=7.5),
axis.line.x=element_blank(),
axis.line.y=element_line(),
axis.ticks.x=element_blank(),
axis.ticks.y=element_line(),
axis.ticks.length=unit(0.5,'cm'),
panel.grid.major.x=element_line(linetype="solid",colour="white",size=1.1),
panel.grid.major.y=element_blank()
)

竖排分面:

柱形分面(竖排):


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
p1<-ggplot(mydata,aes(Conpany,Sale,fill=Year))+
geom_bar(stat="identity",position="dodge")+
theme_wsj()+
scale_fill_wsj("rgby", "")+
theme(axis.ticks.length=unit(0.3,'cm'))+
guides(fill=guide_legend(title=NULL))+
ggtitle("The Financial Performance of Five Giant")+
theme(axis.title = element_blank(),legend.position='none')+
facet_grid(Year~.)
p2<-ggplot(mydata,aes(Conpany,Sale,fill=Year))+
geom_bar(stat="identity",position="dodge")+
theme_economist(base_size=14)+
facet_grid(Year~.)+
scale_fill_economist()+
theme(axis.ticks.length=unit(0.3,'cm'))+
guides(fill=guide_legend(title=NULL))+
ggtitle("The Financial Performance of Five Giant")+
theme(
axis.title = element_blank(),
legend.position='none',
axis.text.y=element_text(size=7.5),
axis.text.x=element_text(size=7.5,face="bold"),
strip.text=element_text(size=10)
)

使用multiplot函数进行版面合并:

1
2
3
require(grid)
library("Rmisc")
multiplot(p1,p2,cols=2)

条形分面(竖排):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ggplot(mydata,aes(Conpany,Sale,fill=Year))+
geom_bar(stat="identity",position="dodge")+
theme_wsj()+
facet_grid(Year~.)+
coord_flip()+
scale_fill_wsj("rgby", "")+
theme(axis.ticks.length=unit(0.5,'cm'))+
guides(fill=guide_legend(title=NULL))+
ggtitle("The Financial Performance of Five Giant")+
theme(
axis.title = element_blank(),
legend.position='none',
panel.grid.major.x=element_line(linetype="dashed",colour="grey60"),
panel.grid.major.y=element_blank(),
axis.ticks.x=element_blank(),
axis.ticks.y=element_line(),
axis.ticks.length=unit(0.3,'cm'),
axis.line.x=element_blank(),
axis.line.y=element_line(),
axis.text.x=element_text(size=10),
)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ggplot(mydata,aes(Conpany,Sale,fill=Year))+
geom_bar(stat="identity",position="dodge")+
facet_grid(Year~.)+
coord_flip()+
theme_economist(base_size=14)+
scale_fill_economist()+
guides(fill=guide_legend(title=NULL))+
ggtitle("The Financial Performance of Five Giant")+
theme(
axis.title = element_blank(),
legend.position='none',
panel.grid.major.x=element_line(linetype=1,colour="white",size=1.1),
panel.grid.major.y=element_blank(),
axis.ticks.x=element_blank(),
axis.ticks.y=element_line(),
axis.ticks.length=unit(0.2,'cm'),
axis.line.x=element_blank(),
axis.line.y=element_line(),
axis.text.x=element_text(size=10),
strip.text=element_text(size=10),
axis.text.y=element_text(size=10)
)

关于簇状、分面图表数据标签问题:

簇状图数据标签处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
ggplot(mydata,aes(Conpany,Sale,fill=Year,label =Sale))+
geom_bar(stat="identity",position="dodge")+
theme_wsj()+
scale_fill_wsj("rgby", "")+
guides(fill=guide_legend(title=NULL))+
ggtitle("The Financial Performance of Five Giant")+
geom_text(aes(y = Sale + 0.05), position =position_dodge(0.9),fontface="bold", vjust =1,colour="white",size=2)+
theme(
axis.title = element_blank(),
axis.ticks.length=unit(0.3,'cm'),
axis.text.x=element_text(size=10),
axis.text.y=element_text(size=10),
)

横向分面柱图数据标签问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ggplot(mydata,aes(Conpany,Sale,fill=Year,label =Sale))+
geom_bar(stat="identity",position="dodge")+
theme_wsj()+
facet_grid(.~Year)+
scale_fill_wsj("rgby", "")+
guides(fill=guide_legend(title=NULL))+
ggtitle("The Financial Performance of Five Giant")+
geom_text(aes(y = Sale + 0.05), position =position_dodge(0.9),fontface="bold", vjust =1,colour="white",size=2)+
theme(
axis.title = element_blank(),
legend.position='none',
axis.ticks.length=unit(0.3,'cm'),
axis.line.x=element_line(),
axis.text.x=element_text(size=5),
axis.text.y=element_text(size=7.5)
)

横向分面条形图数据标签问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ggplot(mydata,aes(Conpany,Sale,fill=Year,label =Sale))+
geom_bar(stat="identity",position="dodge")+
coord_flip()+facet_grid(.~Year)+
theme_wsj()+scale_fill_wsj("rgby", "")+
guides(fill=guide_legend(title=NULL))+
ggtitle("The Financial Performance of Five Giant")+
geom_text(aes(y = Sale + 0.05), position = position_dodge(0.9),hjust=1.2,vjust=0.5,colour="white",size=4)+
theme(
axis.title = element_blank(),
legend.position='none',
panel.grid.major.x=element_line(linetype="dashed",colour="grey60"),
panel.grid.major.y=element_blank(),
axis.ticks.x=element_blank(),
axis.ticks.y=element_line(),
axis.ticks.length=unit(0.3,'cm'),
axis.line.x=element_blank(),
axis.line.y=element_line(),
axis.text.x=element_text(size=8),
axis.text.y=element_text(size=10)
)

竖向分面柱形图数据标签问题:

竖向分面条形图数据标签问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ggplot(mydata,aes(Conpany,Sale,fill=Year,label =Sale))+
geom_bar(stat="identity",position="dodge")+
theme_wsj()+scale_fill_wsj("rgby", "")+
facet_grid(Year~.)+coord_flip()+
guides(fill=guide_legend(title=NULL))+
ggtitle("The Financial Performance of Five Giant")+
geom_text(aes(y = Sale + 0.05), position = position_dodge(0.9),hjust=1.1,colour="white",size=3.5)+
theme(
axis.title = element_blank(),
legend.position='none',
panel.grid.major.x=element_line(linetype="dashed",colour="grey60"),
panel.grid.major.y=element_blank(),
axis.ticks.x=element_blank(),
axis.ticks.y=element_line(),
axis.ticks.length=unit(0.25,'cm'),
axis.line.x=element_blank(),
axis.line.y=element_line(),
axis.text.y=element_text(size=10),
axis.text.x=element_text(size=10)
)

以上是本人在学习ggplot函数过程中的一些练习案例,当然要是仔细琢磨,里面的瑕疵还不少,改进空间还有很多,以后有机会慢慢跟大家补充,过几天再跟大家继续分享关于ggplot更加精深的用法技巧!


联系方式:

wechat:ljty1991
Mail:578708965@qq.com
个人公众号:数据小魔方(datamofang)

qq交流群:[魔方学院]298236508

个人简介:

杜雨
财经专业研究僧;
伪数据可视化达人;
文科背景的编程小白;
喜欢研究商务图表与地理信息数据可视化,爱倒腾PowerBI、SAP DashBoard、Tableau、R ggplot2、Think-cell chart等诸如此类的数据可视化软件,创建并运营微信公众号“数据小魔方”。
Mail:578708965@qq.com


备注信息:

知识共享许可协议
本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。

坚持原创技术分享,您的支持将鼓励我继续创作!