使用geom_bar()函數繪制條形圖,條形圖的高度通常表示兩種情況之一:每組中的數據的個數,或數據框中列的值,高度表示的含義是由geom_bar()函數的參數stat決定的,stat在geom_bar()函數中有兩個有效值:count和identity。默認情況下,stat="count",這意味着每個條的高度等於每組中的數據的個數,並且,它與映射到y的圖形屬性不相容,所以,當設置stat="count"時,不能設置映射函數aes()中的y參數。如果設置stat="identity",這意味着條形的高度表示數據數據的值,而數據的值是由aes()函數的y參數決定的,就是說,把值映射到y,所以,當設置stat="identity"時,必須設置映射函數中的y參數,把它映射到數值變量。
geom_bar()函數的定義是:
geom_bar(mapping = NULL, data = NULL, stat = "count", width=0.9, position="stack")
參數注釋:
- stat:設置統計方法,有效值是count(默認值) 和 identity,其中,count表示條形的高度是變量的數量,identity表示條形的高度是變量的值;
- position:位置調整,有效值是stack、dodge和fill,默認值是stack(堆疊),是指兩個條形圖堆疊擺放,dodge是指兩個條形圖並行擺放,fill是指按照比例來堆疊條形圖,每個條形圖的高度都相等,但是高度表示的數量是不盡相同的。
- width:條形圖的寬度,是個比值,默認值是0.9
- color:條形圖的線條顏色
- fill:條形圖的填充色
關於stat參數,有三個有效值,分別是count、identity和bin:
- count是對離散的數據進行計數,計數的結果用一個特殊的變量..count.. 來表示,
- bin是對連續變量進行統計轉換,轉換的結果使用變量..density..來表示
- 而identity是直接引用數據集中變量的值
position參數也可以由兩個函數來控制,參數vjust和widht是相對值:
position_stack(vjust = 1, reverse = FALSE) position_dodge(width = NULL) position_fill(vjust = 1, reverse = FALSE)
本文使用vcd包中的Arthritis數據集來演示如何創建條形圖。
head(Arthritis) ID Treatment Sex Age Improved 1 57 Treated Male 27 Some 2 46 Treated Male 29 None 3 77 Treated Male 30 None 4 17 Treated Male 32 Marked 5 36 Treated Male 46 Marked 6 23 Treated Male 58 Marked
其中變量Improved和Sex是因子類型,ID和Age是數值類型。
一,繪制基本的條形圖
使用geom_bar()函數繪制條形圖,
ggplot(data=ToothGrowth, mapping=aes(x=dose))+ geom_bar(stat="count")
當然,我們也可以先對數據進行處理,得到按照Improved進行分類的頻數分布表,然后使用geom_bar()繪制條形圖:
mytable <- with(Arthritis,table(Improved)) df <- as.data.frame(mytable) ggplot(data=df, mapping=aes(x=Improved,y=Freq))+ geom_bar(stat="identity")
繪制的條形圖是相同的,如下圖所示:
二,修改條形圖的圖形屬性
條形圖的圖形屬性包括條形圖的寬度,條形圖的顏色,條形圖的標簽,分組和修改圖例的位置等。
1,修改條形圖的寬度和顏色
把條形圖的相對寬度設置為0.5,線條顏色設置為red,填充色設置為steelblue
ggplot(data=Arthritis, mapping=aes(x=Improved))+ geom_bar(stat="count",width=0.5, color='red',fill='steelblue')
2,設置條形圖的文本
使用geom_text()為條形圖添加文本,顯示條形圖的高度,並調整文本的位置和大小。
當stat="count"時,設置文本的標簽需要使用一個特殊的變量 aes(label=..count..), 表示的是變量值的數量。
ggplot(data=Arthritis, mapping=aes(x=Improved))+ geom_bar(stat="count",width=0.5, color='red',fill='steelblue')+ geom_text(stat='count',aes(label=..count..), vjust=1.6, color="white", size=3.5)+ theme_minimal()
當stat="identity"時,設置文本的標簽需要設置y軸的值,aes(lable=Freq),表示的變量的值。
mytable <- with(Arthritis,table(Improved)) df <- as.data.frame(mytable) ggplot(data=df, mapping=aes(x=Improved,y=Freq))+ geom_bar(stat="identity",width=0.5, color='red',fill='steelblue')+ geom_text(aes(label=Freq), vjust=1.6, color="white", size=3.5)+ theme_minimal()
添加文本數據之后,顯示的條形圖是:
3,按照分組修改條形圖的圖形屬性
把條形圖按照Improved變量進行分組,設置每個分組的填充色,這通過aes(fill=Improved)來實現,每個分組的填充色依次是scale_color_manual()定義的顏色:
ggplot(data=Arthritis, mapping=aes(x=Improved,fill=Improved))+ geom_bar(stat="count",width=0.5)+ scale_color_manual(values=c("#999999", "#E69F00", "#56B4E9"))+ geom_text(stat='count',aes(label=..count..), vjust=1.6, color="white", size=3.5)+ theme_minimal()
4,修改圖例的位置
修改圖例的位置,通過theme(legend.position=) 來實現,默認的位置是right,有效值是right、top、bottom、left和none,其中none是指移除圖例。
p <- ggplot(data=Arthritis, mapping=aes(x=Improved,fill=Improved))+ geom_bar(stat="count",width=0.5)+ scale_color_manual(values=c("#999999", "#E69F00", "#56B4E9"))+ geom_text(stat='count',aes(label=..count..), vjust=1.6, color="white", size=3.5)+ theme_minimal() p + theme(legend.position="top") p + theme(legend.position="bottom") # Remove legend p + theme(legend.position="none")
5,修改條形圖的順序
通過scale_x_discrete()函數修改標度的順序:
p <- ggplot(data=Arthritis, mapping=aes(x=Improved,fill=Improved))+ geom_bar(stat="count",width=0.5)+ scale_color_manual(values=c("#999999", "#E69F00", "#56B4E9"))+ geom_text(stat='count',aes(label=..count..), vjust=1.6, color="white", size=3.5)+ theme_minimal() p + scale_x_discrete(limits=c("Marked","Some", "None"))
三,包含分組的條形圖
分組的條形圖如何擺放,是由geom_bar()函數的position參數確定的,默認值是stack,表示堆疊擺放、dodge表示並行擺放、fill表示按照比例來堆疊條形圖。
1,堆疊擺放
設置geom_bar()的position參數為"stack",在向條形圖添加文本時,使用position=position_stack(0.5),調整文本的相對位置。
ggplot(data=Arthritis, mapping=aes(x=Improved,fill=Sex))+ geom_bar(stat="count",width=0.5,position='stack')+ scale_fill_manual(values=c('#999999','#E69F00'))+ geom_text(stat='count',aes(label=..count..), color="white", size=3.5,position=position_stack(0.5))+ theme_minimal()
2,並行擺放
調整y軸的最大值,使用position=position_dodge(0.5),vjust=-0.5 來調整文本的位置
y_max <- max(aggregate(ID~Improved+Sex,data=Arthritis,length)$ID) ggplot(data=Arthritis, mapping=aes(x=Improved,fill=Sex))+ geom_bar(stat="count",width=0.5,position='dodge')+ scale_fill_manual(values=c('#999999','#E69F00'))+ ylim(0,y_max+5)+ geom_text(stat='count',aes(label=..count..), color="black", size=3.5,position=position_dodge(0.5),vjust=-0.5)+ theme_minimal()
3,按照比例堆疊條形圖
需要設置geom_bar(position="fill"),並使用geom_text(position=position_fill(0.5))來調整文本的位置,如果geom_text(aes(lable=..count..)),那么表示文本顯示的值是變量的數量:
ggplot(data=Arthritis, mapping=aes(x=Improved,fill=Sex))+ geom_bar(stat="count",width=0.5,position='fill')+ scale_fill_manual(values=c('#999999','#E69F00'))+ geom_text(stat='count',aes(label=..count..), color="white", size=3.5,position=position_fill(0.5))+ theme_minimal()
該模式最大的特點是可以把文本顯示為百分比:
ggplot(data=Arthritis, mapping=aes(x=Improved,fill=Sex))+ geom_bar(stat="count",width=0.5,position='fill')+ scale_fill_manual(values=c('#999999','#E69F00'))+ geom_text(stat='count',aes(label=scales::percent(..count../sum(..count..))) , color="white", size=3.5,position=position_fill(0.5))+ theme_minimal()
四,增加注釋和旋轉坐標軸
在繪制條形圖時,需要動態設置注釋(annotate)的位置x和y,x和y的值是由條形圖的高度決定的,
annotate(geom="text", x = NULL, y = NULL)
在繪制條形圖時,可以動態設置x和y的大小:
library("ggplot2") library("dplyr") library("scales") #win.graph(width=6, height=5,pointsize=8) #data df <- data.frame( rate_cut=rep(c("0 Change", "0 - 10", "10 - 20", "20 - 30", "30 - 40","40 - 50", "50 - 60", "60 - 70","70 - 80", "80 - 90", "90 - 100", ">100"),2) ,freq=c(1,3,5,7,9,11,51,61,71,13,17,9, 5,7,9,11,15,19,61,81,93,17,21,13) ,product=c(rep('ProductA',12),rep('ProductB',12)) ) #set order labels_order <- c("0 Change", "0 - 10", "10 - 20", "20 - 30", "30 - 40","40 - 50", "50 - 60", "60 - 70","70 - 80", "80 - 90", "90 - 100", ">100") #set plot text plot_legend <- c("Product A", "Product B") plot_title <- paste0("Increase % Distribution") annotate_title <-"Top % Increase" annotate_prefix_1 <-"Product A = " annotate_prefix_2 <-"Product B = " df_sum <- df %>% group_by(product) %>% summarize(sumFreq=sum(freq))%>% ungroup()%>% select(product,sumFreq) df <- merge(df,df_sum,by.x = 'product',by.y='product') df <- within(df,{rate <- round(freq/sumFreq,digits=4)*100}) df <- subset(df,select=c(product,rate_cut,rate)) #set order df$rate_cut <- factor(df$rate_cut,levels=labels_order,ordered = TRUE) df <- df[order(df$product,df$rate_cut),] #set position annotate.y <- ceiling(max(round(df$rate,digits = 0))/4*2.5) text.offset <- max(round(df$rate,digits = 0))/25 annotation <- df %>% mutate(indicator = ifelse(substr(rate_cut,1,2) %in% c("70","80","90",'>1'),'top','increase' )) %>% filter(indicator=='top') %>% dplyr::group_by(product) %>% dplyr::summarise(total = sum(rate)) %>% select(product, total) mytheme <- theme_classic() + theme( panel.background = element_blank(), strip.background = element_blank(), panel.grid = element_blank(), axis.line = element_line(color = "gray95"), axis.ticks = element_blank(), text = element_text(family = "sans"), axis.title = element_text(color = "gray30", size = 12), axis.text = element_text(size = 10, color = "gray30"), plot.title = element_text(size = 14, hjust = .5, color = "gray30"), strip.text = element_text(color = "gray30", size = 12), axis.line.y = element_line(size=1,linetype = 'dotted'), axis.line.x = element_blank(), axis.text.x = element_text(vjust = 0), plot.margin = unit(c(0.5,0.5,0.5,0.5), "cm"), legend.position = c(0.7, 0.9), legend.text = element_text(color = "gray30") ) ##ggplot ggplot(df,aes(x=rate_cut, y=rate)) + geom_bar(stat = "identity", aes(fill = product), position = "dodge", width = 0.5) + guides(fill = guide_legend(reverse = TRUE)) + scale_fill_manual(values = c("#00188F","#00BCF2") ,breaks = c("ProductA","ProductB") ,labels = plot_legend ,name = "") + geom_text(data = df , aes(label = comma(rate), y = rate +text.offset, color = product) ,position = position_dodge(width =1) , size = 3) + scale_color_manual(values = c("#00BCF2", "#00188F"), guide = FALSE) + annotate("text", x = 3, y = annotate.y, hjust = 0, color = "gray30", label = annotate_title) + annotate("text", x = 2.5, y = annotate.y, hjust = 0, color = "gray30", label = paste0(annotate_prefix_1, annotation$total[1])) + annotate("text", x = 2, y = annotate.y, hjust = 0, color = "gray30", label = paste0(annotate_prefix_2, annotation$total[2])) + labs(x="Increase Percentage",y="Percent of freq",title=plot_title) + mytheme + coord_flip()
參考文檔:
ggplot2 barplots : Quick start guide - R software and data visualization