京公网安备 11010802034615号
经营许可证编号:京B2-20210330
一场用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()
)
![]()
因水平有限,代码写的比较糟糕,图表如有可改善的细节,还请的各位多多指点。
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
在数字化时代,每一位用户与产品的交互都会留下可追溯的行为轨迹——电商用户的浏览、加购、下单,APP用户的注册、登录、功能使 ...
2026-03-31在日常数据统计、市场调研、学术分析等场景中,我们常常需要判断两个分类变量之间是否存在关联(如性别与消费偏好、产品类型与满 ...
2026-03-31在CDA(Certified Data Analyst)数据分析师的职场实战与认证考核中,“可解释性建模”是核心需求之一——企业决策中,不仅需要 ...
2026-03-31多层感知机(MLP,Multilayer Perceptron)作为深度学习中最基础、最经典的神经网络模型,其结构设计直接决定了模型的拟合能力、 ...
2026-03-30在TensorFlow深度学习实战中,数据集的加载与预处理是基础且关键的第一步。手动下载、解压、解析数据集不仅耗时费力,还容易出现 ...
2026-03-30在CDA(Certified Data Analyst)数据分析师的日常工作中,“无监督分组、挖掘数据内在聚类规律”是高频核心需求——电商场景中 ...
2026-03-30机器学习的本质,是让模型通过对数据的学习,自主挖掘规律、实现预测与决策,而这一过程的核心驱动力,并非单一参数的独立作用, ...
2026-03-27在SQL Server数据库操作中,日期时间处理是高频核心需求——无论是报表统计中的日期格式化、数据筛选时的日期类型匹配,还是业务 ...
2026-03-27在CDA(Certified Data Analyst)数据分析师的能力体系与职场实操中,高维数据处理是高频且核心的痛点——随着业务场景的复杂化 ...
2026-03-27在机器学习建模与数据分析实战中,特征维度爆炸、冗余信息干扰、模型泛化能力差是高频痛点。面对用户画像、企业经营、医疗检测、 ...
2026-03-26在这个数据无处不在的时代,数据分析能力已不再是数据从业者的专属技能,而是成为了职场人、管理者、创业者乃至个人发展的核心竞 ...
2026-03-26在CDA(Certified Data Analyst)数据分析师的能力体系中,线性回归是连接描述性统计与预测性分析的关键桥梁,也是CDA二级认证的 ...
2026-03-26在数据分析、市场研究、用户画像构建、学术研究等场景中,我们常常会遇到多维度、多指标的数据难题:比如调研用户消费行为时,收 ...
2026-03-25在流量红利见顶、获客成本持续攀升的当下,营销正从“广撒网”的经验主义,转向“精耕细作”的数据驱动主义。数据不再是营销的辅 ...
2026-03-25在CDA(Certified Data Analyst)数据分析师的全流程工作中,无论是前期的数据探索、影响因素排查,还是中期的特征筛选、模型搭 ...
2026-03-25在当下数据驱动决策的职场环境中,A/B测试早已成为互联网产品、运营、营销乃至产品迭代优化的核心手段,小到一个按钮的颜色、文 ...
2026-03-24在统计学数据分析中,尤其是分类数据的分析场景里,卡方检验和显著性检验是两个高频出现的概念,很多初学者甚至有一定统计基础的 ...
2026-03-24在CDA(Certified Data Analyst)数据分析师的日常业务分析与统计建模工作中,多组数据差异对比是高频且核心的分析场景。比如验 ...
2026-03-24日常用Excel做数据管理、台账维护、报表整理时,添加备注列是高频操作——用来标注异常、说明业务背景、记录处理进度、补充关键 ...
2026-03-23作为业内主流的自助式数据可视化工具,Tableau凭借拖拽式操作、强大的数据联动能力、灵活的仪表板搭建,成为数据分析师、业务人 ...
2026-03-23