今天我们学习另外一种柱状图,堆积柱状图,就是把每一个组的量堆积起来画成一个柱状图。
用自带的一个测试数据。
library(reshape2)
library(ggplot2)
data = datasets::attitude
head(data)
从测试数据来看,是一个包含30个样本,7个变量的数据。下面我们查看每个样本的scale是否一样。先查看一下总和,我们利用apply函数。
apply函数:对矩阵、数据框、数组(二维、多维)等矩阵型数据,按行或列应用函数FUN进行循环计算,并以返回计算结果
apply(X, MARGIN, FUN, ...)
X:数组、矩阵、数据框等矩阵型数据
MARGIN: 按行计算或按按列计算,1表示按行,2表示按列
FUN: 自定义的调用函数
statistics = apply(data, 1, sum)
statistics
plot(statistics)
从图中可以看出每个样本的sum是不一样的,如果要画堆积图的话,就不一样的比例了。所以我们转化成百分比来画。
df = data.frame()
for (n in 1:nrow(data))
{
df = rbind(df, data[n,]/statistics[n])
}
statistics = apply(df, 1, sum)
statistics
plot(statistics)
可以看出,转化成百分比之后,每个样本中的scale是一样的,都是1。
df$name =paste("c",seq(1,nrow(df),1),sep="")
我们再手动的添加了名字上去,方面后面做演示。
#作图前有个很重要的前置动作,要把宽矩阵转换为长矩阵。通过melt函数来实现。melt(短数据名称,id="不做变换的列名",variable=“自定义”value=“自定义”)。其中variable和value的值可自定义,默认值为variable和value。
data_plot = melt(df,id = "name")
从data_plot可以看出,变成了短数据,主要是把每一列都转化成了行的形式。
group = c(rep("g1",6),rep("g2",6),rep("g3",6),rep("g4",6),rep("g5",6))
group2 =rep(group,ncol(data))
level=paste("c",seq(1,nrow(df),1),sep="")
data_plot$group=group2 #我们又手动的添加了分组的标签,方面后面操作
data_plot$name=factor(data_plot$name,levels=level) #为了让按照我们想要的顺序排序,我们把name设置成了因子
ggplot( data_plot, aes( x = name, weight = value, fill = variable))+
geom_bar( position = "stack")
下面就生成了一个基本的堆积图。
如果把"stack"改成"dodge",可以变成分组柱状图。
ggplot( data_plot, aes( x = name, weight = value, fill = variable))+
geom_bar( position = "dodge")
可以手动的改颜色等,当然values里面也可以自定义颜色。
ggplot( data_plot, aes( x = name, weight = value, fill = variable))+
geom_bar( position = "stack")+
scale_fill_manual( values = rainbow(7))
也可以根据我们设置的group来分面板来画。
ggplot( data_plot, aes( x = name, weight = value, fill = variable))+
geom_bar( position = "stack",width=0.9)+
scale_fill_manual( values = rainbow(7))+
xlab("people")+
ylab("percent")+
theme_classic()+
theme(text = element_text(size = 15))+
theme(axis.text = element_text(face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1))+
facet_wrap(group~.,scales="free_x",nrow = 1)+
theme(strip.background=element_rect(fill = c("blue")))
比如,如果我们想按照variable占的比例来排序,一般情况下,最多的在最下面,就需要指定variable为factor了。
order_x = apply(df[,1:7], 2, sum) # 查看各列 variable的总和
order_x = order_x[order(order_x, decreasing = F)] # decreasing = T 代表是倒序
order_x # 看一下,是从大到小排着的
# 此时 data_plot数据框里面的 variable就按照给定的 levels 排序了
data_plot$variable= factor(data_plot$variable,
levels = names(order_x) ,
ordered = T )
ggplot( data_plot, aes( x = name, weight = value, fill = variable))+
geom_bar( position = "stack",width=0.9)+
scale_fill_manual( values = rainbow(7))+
xlab("people")+
ylab("percent")+
theme_classic()+
theme(text = element_text(size = 15))+
theme(axis.text = element_text(face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1))+
facet_wrap(group~.,scales="free_x",nrow = 1)+
theme(strip.background=element_rect(fill = c("blue")))
柱状图里面书序就改成我们想要的顺序了。
其实用我们前面用的boxplot来查看比例更为清晰一点。
ggplot(data_plot, aes( x = variable, y= value, fill = variable))+
geom_boxplot()
library(RColorBrewer)
a <- brewer.pal(7,"Set1")
a <- terrain.colors(7)
a <- heat.colors(7)
a <- topo.colors(7)
ggplot( data_plot, aes( x = name, weight = value, fill = variable))+
geom_bar( position = "stack",width=0.9)+
scale_fill_manual( values = rainbow(7))+
#scale_fill_manual( values = a)+
xlab("people")+
ylab("percent")+
theme_classic()+
theme(text = element_text(size = 15))+
theme(axis.text = element_text(face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1))+
facet_wrap(group~.,scales="free_x",nrow = 1)+
theme(strip.background=element_rect(fill = c("gray")))+
scale_y_continuous(expand = c(0,0)) #消除Y轴两端的留白区域
我们进行了微调格式以下,比如可以更换不同的色系等。