【ggplot】复杂柱状图:自定义颜色、标签、位置、坐标轴和主题

时间:2022-04-22 17:37:52

一直想有机会好好梳理下ggplot的图形,但是一般情况下ggplot常用的图形还是一些线图和柱状图,但是使用ggplot的好处(对比excel)就是R在处理大数据可以不用切换软件直接截取,但是坏处就是相对excel的某些时刻略有复杂,但是如果ggplot连excel的基本画图效率都比不过的话,也就失去了存在的意义。

简单的图形当然ggplot官方文档中就有,主要呈现以下复杂的ggplot的柱状图。首先还是载入下我的ggplot主题:

因为工作需要,ppt的模板都有固定颜色,这边颜色设定如下:

windowsFonts(A=windowsFont('等线'),B=windowsFont('微软雅黑'))
par(family='A')
pptblue<-rgb(r=16,g=77,b=96,maxColorValue = 255)
pptgrey<-rgb(r=107,g=107,b=107,maxColorValue = 255)
pptred<-rgb(r=233,g=77,b=96,maxColorValue = 255)
ppttea<-rgb(r=198,g=96,b=52,maxColorValue = 255)
pptdark<-rgb(r=69,g=87,b=101,maxColorValue = 255)
pptbg<-rgb(r=242,g=242,b=242,maxColorValue = 255)
par(bg=pptbg)
par(bty='l')
par(mar=c(4,5,4,6))

然后是对应颜色的主题:

theme1<-theme_bw()+theme(legend.position = 'top', #图例位置
text=element_text(family='A'), #字体
panel.background=element_rect(pptbg), #画布背景颜色
plot.background=element_rect(pptbg), #图形背景颜色
plot.title = element_text(hjust=0.5,size=16,vjust=0.5), #标题位置
panel.border=element_blank(),#图形边界
panel.grid.major=element_line(colour='lightgrey',linetype="dashed"), #网格线
panel.grid.minor=element_blank(), #次级网格线
legend.title=element_text(size=10,colour='black',family='A',vjust=-0.5), #图例标题
legend.text=element_text(size=10,colour='black',family='A'), #图例文字
legend.background =element_rect(pptbg),#图例背景
axis.text=element_text(size=12,colour="black",family='A'), #坐标轴文字
strip.text=element_text(size=12,colour="black",family='A'),#分面文字
strip.background=element_blank(),#分面的背景
axis.line = element_line(size=0.5, colour = 'black'), #轴颜色大小
panel.spacing=unit(10,'mm') #画布大小

这个主题没啥好说的,就是改了下图例的位置,文字的字体等;

ok,背景主题设置完毕,下面看下如何做柱状图:

数据集还是选择iris数据集。

先看下iris数据集

head(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width
1 5.1 3.5 1.4 0.2
2 4.9 3.0 1.4 0.2
3 4.7 3.2 1.3 0.2
4 4.6 3.1 1.5 0.2
5 5.0 3.6 1.4 0.2
6 5.4 3.9 1.7 0.4
Species
1 setosa
2 setosa
3 setosa
4 setosa
5 setosa
6 setosa

我们很熟悉的iris有四个变量,三个类别,如果我们第一个复杂的柱状图想看下三个类别分别的四个变量的占比和数值之类的信息,也就是我们需要三个柱子,每个柱子内部开始堆叠;

第一步,需要对数据进行整形,我们都知道ggplot需要长格式的数据,而且我们看分布,其实就是看一个求和,那么:

library(data.table)
iris1<-melt(iris,
id.vars='Species',
measure.vars=c('Sepal.Length','Sepal.Width','Petal.Length','Petal.Width'))

iris1<-data.table(iris1)

则iris1为:

iris1
Species variable value
1: setosa Sepal.Length 5.1
2: setosa Sepal.Length 4.9
3: setosa Sepal.Length 4.7
4: setosa Sepal.Length 4.6
5: setosa Sepal.Length 5.0
---
596: virginica Petal.Width 2.3
597: virginica Petal.Width 1.9
598: virginica Petal.Width 2.0
599: virginica Petal.Width 2.3
600: virginica Petal.Width 1.8

这次我们把每个变量都放在了variable这个里面,但是我们还需要进行求和:

iris1_1<-iris1[,list(sumvalue=sum(value)),by=list(Species,variable)]
setorder(iris1_1,Species)

最后整形后的是:

iris1_1
Species variable sumvalue
1: setosa Sepal.Length 250.3
2: setosa Sepal.Width 171.4
3: setosa Petal.Length 73.1
4: setosa Petal.Width 12.3
5: versicolor Sepal.Length 296.8
6: versicolor Sepal.Width 138.5
7: versicolor Petal.Length 213.0
8: versicolor Petal.Width 66.3
9: virginica Sepal.Length 329.4
10: virginica Sepal.Width 148.7
11: virginica Petal.Length 277.6
12: virginica Petal.Width 101.3

也就是三类,每个类别四个值,为四个变量的加和。

下面需要调整下标签,因为ggplot的标签分两部分,第一部分是位置,第二部分是值;值很好说,但是位置默认是高度,也就是堆叠的高度。而我们这次需要不放在那个顶部,而是放在中部,所以这个位置需要手工调整下。

#设置标签的高度,累计的高度为堆叠上面的一半
iris1_2<-iris1_1[,label_y:=cumsum(sumvalue)-sumvalue/2,by=list(Species)]

然后画一个图:

ggplot(iris1_2,aes(x=Species,
y=sumvalue,
fill=variable))+
geom_bar(stat='identity',
position=position_stack(reverse=T))+ #本来不用reverse是从上到下,反过来
theme1+
geom_text(aes(x=Species,y=label_y,label=sumvalue),
position='identity', #既然已经算出来label高度了,就不能stack
color='white')+
ggtitle('堆叠柱状图')+
scale_fill_manual(name='图例', #图例项(或者用scale_fill_discrete)
labels=c('1-SL','2-SW','3-PL','4-PW'), #图例标签
values=c('darkgreen','red','darkblue','black'))+ #颜色
scale_x_discrete(name='类别', #x轴坐标名称
labels=c('1-Setosa','2-Versicolor','3-Virginica'))+ #离散的标签
scale_y_continuous(name='值', #y轴坐标名称
breaks=seq(0,1000,100),
limits=c(0,900)) #连续的标签和坐标轴

图形为:
【ggplot】复杂柱状图:自定义颜色、标签、位置、坐标轴和主题

除了堆叠柱状图,还有一个常用的就是普通柱状图,也就是并列摆放的类型。

在这个图中,我们可以自定义图例、文字颜色和坐标轴,如下:

ggplot(iris1_2,aes(x=factor(Species,
levels=levels(iris1_2$Species)[c(3,2,1)]),
y=sumvalue,
fill=factor(variable,
levels=levels(iris1_2$variable)[c(4,3,2,1)])))+
geom_bar(stat='identity',
position=position_dodge())+ #本来不用reverse是从上到下,反过来
theme1+
geom_text(aes(x=Species,y=sumvalue+20,label=sumvalue,
color=factor(variable,
levels=levels(iris1_2$variable)[c(4,3,2,1)])),#和fill的一致
position=position_dodge(width=0.9),
show.legend = F)+#showlegend 隐藏文字的图例
ggtitle('柱状图')+
scale_fill_discrete(name='图例', #图例项(或者用scale_fill_discrete)
labels=levels(iris1_2$variable)[c(4,3,2,1)])+ #颜色
scale_x_discrete(name='类别', #x轴坐标名称
labels=levels(iris1_2$Species)[c(3,2,1)])+ #离散的标签
scale_y_continuous(name='值', #y轴坐标名称
breaks=seq(0,400,50),
limits=c(0,400))#连续的标签和坐标轴

对应的图形是:

【ggplot】复杂柱状图:自定义颜色、标签、位置、坐标轴和主题