登录
首页精彩阅读一场用R语言打造的商务图表视觉盛宴
一场用R语言打造的商务图表视觉盛宴
2017-04-07
收藏

一场用R语言打造的商务图表视觉盛宴

之前已经模仿了挺多网络上流行的高难度商务图表案例,自觉功力有所小成,就想着趁热打铁,把那些剩余的还没有被挖掘出来了的商务图表案例全部补全。

本篇给出不等宽柱形图案例以及MEKKO(也称市场细分矩阵)图案例全部四张图的R语言代码,作为ggplot商务图表进阶道路上的一个小小一步。

因素需要构造自定义标度,这里需要scale包的支持

library(ggplot2)

library(scales)

构造不等宽柱形图的案例数据(本案例模仿对象是刘万祥老师的《Excel图表之道》,感谢老师在业界的无私奉献精神,给我后备爱或者留下了如此丰富的图表案例资源,这里再次向老师致敬!)。

mydata<-data.frame(Name=paste0("项目",1:5),Scale=c(35,30,20,10,5),ARPU=c(56,37,63,57,59))

因为本篇 所构造的不等宽柱形图、MEKKO矩阵图等都是建立在四边形(或者呈为矩阵)的基础图形之上的,即物理的二维空间中,四个点坐标可以定位出一个四边形,利用R语言的向量化操作,就可以同时操纵n组长度为4的向量,来批量生成矩形块,这里的核心技巧只是在数据源中准确的生成每一组向量(也即每一个矩形块的水平轴起点、终点、垂直轴的起点、终点)。

在ggplot系统中,生成矩形的图层函数是geom_rect()函数,内置四个参数:

xmin\xmax\ymin\ymax

不等宽柱形图:


#构造矩形X轴的起点(最小点)

mydata$xmin<-0

for (i in 2:5){

mydata$xmin[i]<-sum(mydata$Scale[1:i-1])

}

#构造矩形X轴的终点(最大点)

for (i in 1:5){

mydata$xmax[i]<-sum(mydata$Scale[1:i])

}

#构造数据标签的横坐标:

for (i in 1:5){

mydata$label[i]<-sum(mydata$Scale[1:i])-mydata$Scale[i]/2

}

定义字体:

windowsFonts(myFont = windowsFont("微软雅黑"))

运行ggplot函数:


ggplot(mydata)+

geom_rect(aes(xmin=xmin,xmax=xmax,ymin=0,ymax=ARPU,fill=Name))+

scale_fill_manual(values=c("#54576B","#BD1F12","#E8BA11","#62962A","#9B56AF"))+

geom_text(aes(x=label,y=ARPU-3,label=ARPU),size=6,col="white",family="myFont")+

geom_text(aes(x=label,y=-2.5,label=Scale),size=4,col="black",family="myFont")+

geom_text(aes(x=label,y=-5.5,label=Name),size=4,col="black",family="myFont")+

annotate("text",x=16,y=70,label="不等宽柱形图",size=8,family="myFont")+  

annotate("text",x=14,y=64,label="这是一幅很用心的图表",size=4,family="myFont")+ 

annotate("text",x=11,y=-9.8,label="Source:EasyCharts",size=4,family="myFont")+ 

ylim(-10,80)+

theme_nothing()

-----------------------------------------------------------------------------------------------------------

不等宽条形图

该案例来自于本人小号数据小魔方,也曾在本平台转发过:

图表案例——全球创新国家1000强研发投入变动趋势

设置目录导入数据

mydata<-read.csv("barchart.csv",stringsAsFactors = FALSE) 

names(mydata)[1:5]<-c("State","RD","Betw","Cumcost","class")

#构造矩形X轴的起点(最小点)

mydata$xmin<-0

for (i in 2:nrow(mydata)){

mydata$xmin[i]<-sum(mydata$RD[1:i-1])

}

#构造矩形X轴的终点(最大点)

for (i in 1:nrow(mydata)){

mydata$xmax[i]<-sum(mydata$RD[1:i])

}

#构造数据标签的横坐标:

for (i in 1:nrow(mydata)){

mydata$label[i]<-sum(mydata$RD[1:i])-mydata$RD[i]/2

}

mydata$class<-factor(mydata$class,levels=c("亚洲","欧洲","北美","其他地区")).

运行作图函数:

ggplot(mydata)+

geom_rect(aes(xmin=xmin,xmax=xmax,ymin=0,ymax=Betw,fill=class),col="white")+

coord_flip()+

scale_x_reverse()+

scale_y_continuous(limits=c(-.45,.7),breaks=seq(-.4,.7,.1),labels=percent_format(),position = "top")+

scale_fill_manual(values=c("#802428","#AB6661","#D1A6A1","#A89B94"))+

geom_text(aes(x=label,y=Betw/2,label=Betw),size=3,col="white",family="myFont")+

geom_text(aes(x=label,y=ifelse(Betw>0,Betw+.03,Betw-.033),label=mydata$RD),size=4,col="black",family="myFont")+

geom_text(aes(x=label,y=ifelse(Betw>0,-.07,.07),label=State),size=4,col="black",family="myFont")+

labs(title="不等宽柱形图",subtitle="这是一幅很用心的图表",caption="Source:EasyCharts",x="",y="")+

theme(

text=element_text(family="myFont"),

plot.title=element_text(size=18),

plot.subtitle=element_text(size=14),

plot.caption=element_text(size=10,hjust=0),

plot.background=element_blank(),

panel.background=element_blank(),

panel.grid=element_blank(),

axis.text.y=element_blank(),

axis.ticks.y=element_blank(),

legend.position=c(0.9,0.2),

axis.line.x=element_line()

)

--------------------------------------------------------------------------------------------------------

MEKKO(也称市场细分矩阵)

该图表同样来源于刘老师的图表宝典——《Excel图表之道》

Mekko<-read.csv("Mekko.csv",stringsAsFactors = FALSE) 

Mekko$Class<-factor(Mekko$Class,order=T)

#构造矩形(Obama)X轴的起点(最小点)

Mekko$xmin<-0

for (i in 2:nrow(Mekko)){

Mekko$xmin[i]<-sum(Mekko$percent[1:i-1])

}

#构造矩形(Obama)X轴的终点(最大点)

for (i in 1:nrow(Mekko)){

Mekko$xmax[i]<-sum(Mekko$percent[1:i])

}

#构造数据标签的横坐标:

for (i in 1:nrow(Mekko)){

Mekko$label[i]<-sum(Mekko$percent[1:i])-Mekko$percent[i]/2

}


这里我不想重复映射两次geom_rect()图层函数,所以从新整理了数据源,一定要记得ggplot的作图体系中使用因子变量进行分类作图的思想,这里完全可以用一个类别标量赋给fill属性,避免代码冗余。


mynewdata1<-Mekko[,c(1,6,7)];mynewdata1$ymin<-0;mynewdata1$ymax<-Mekko$Obama;mynewdata1$Type<-"Obama"

mynewdata2<-Mekko[,c(1,6,7)];mynewdata2$ymin<-Mekko$Obama+Mekko$m;mynewdata2$ymax<-Mekko$Obama+Mekko$m+Mekko$McCain;mynewdata2$Type<-"McCain"

mynewdata<-rbind(mynewdata1,mynewdata2)

mynewdata$Type<-factor(mynewdata$Type,levels=c("Obama","McCain"),order=T)

运行作图函数:

ggplot(mynewdata)+

geom_rect(aes(xmin=xmin,xmax=xmax,ymin=ymin,ymax=ymax,fill=Type),col="white")+

scale_fill_manual(values=c("#004C7F","#B70023"))+

scale_x_continuous(breaks=Mekko$label,labels=Mekko$Class)+

geom_text(data=Mekko,aes(x=label,y=.25,label=percent(Obama)),size=3.5,col="white",family="myFont")+

geom_text(data=Mekko,aes(x=label,y=.8,label=percent(McCain)),size=3.5,col="white",family="myFont")+

labs(title="MEKKO-市场细分矩阵图",subtitle="这是一幅用心良苦的图表",caption="Source:EasyCharts",x="",y="")+

theme(

plot.margin=unit(c(2,0,0.5,0),"lines"),

panel.spacing=unit(c(0,0,0,0),"lines"),

axis.text.x=element_text(angle=90,size=10),

panel.background=element_blank(),

axis.ticks=element_blank(),

axis.text.y=element_blank(),

legend.position=c(.78,1),

legend.direction="horizontal",

text=element_text(family="myFont"),

plot.title=element_text(size=18),

plot.subtitle=element_text(size=14),

plot.caption=element_text(size=10,hjust=0),

legend.title=element_blank()

)

---------------------------------------------------------------------------------------------------------

以下同样的数据源,只是通过坐标旋转,换成了条形图的风格。

ggplot(mynewdata)+

geom_rect(aes(xmin=xmin,xmax=xmax,ymin=ymin,ymax=ymax,fill=Type),col="white")+

coord_flip()+

scale_fill_manual(values=c("#004C7F","#B70023"))+

scale_x_continuous(breaks=Mekko$label,labels=Mekko$Class)+

geom_text(data=Mekko,aes(x=label,y=.25,label=percent(Obama)),size=3.5,col="white",family="myFont")+

geom_text(data=Mekko,aes(x=label,y=.8,label=percent(McCain)),size=3.5,col="white",family="myFont")+

labs(title="MEKKO-市场细分矩阵图",subtitle="这是一幅用心良苦的图表",caption="Source:EasyCharts",x="",y="")+

theme(

plot.margin=unit(c(0,0,0,0),"lines"),

panel.spacing=unit(c(0,0,0,0),"lines"),

axis.text.y=element_text(size=10),

panel.background=element_blank(),

axis.ticks=element_blank(),

axis.text.x=element_blank(),

legend.position=c(.78,1),

legend.direction="horizontal",

text=element_text(family="myFont"),

plot.title=element_text(size=18),

plot.subtitle=element_text(size=14),

plot.caption=element_text(size=10,hjust=0),

legend.title=element_blank()

)

因水平有限,代码写的比较糟糕,图表如有可改善的细节,还请的各位多多指点。


数据分析咨询请扫描二维码

客服在线
立即咨询