ggplot2 - 柱状图

简介

柱状图一般用于,当我们都有一组分类变量以及每个类别的定量值,而我们关注的主要重点是定量值的大小时。

  1. 应该在柱状图背景保留横网格线,便于比较我们关注的值。

  2. 当分类label过长时,最好选择横向柱状图,避免出现旋转label,保持文字阅读方向与图形方向的统一性。

  3. 应该注意对柱状图进行排序(大小,分类变量,分布心态)。

  4. 当分类数据过多时,可以选择棒棒糖图(点图 + 点到坐标轴连线)或热图

ggplot2中柱状图的基本绘制函数有geom_bar() 和 geom_col(),其中geom_bar() 产生的柱状图映射是经过统计变换的(count, ..prop..);geom_col()是不经过统计变换的,代表的就是该分类变量的实际值。

1. 美学映射

  • x

  • y

  • alpha

  • colour

  • fill

  • group

  • linetype

  • size

ggplot2中柱状图的基本绘制函数有geom_bar() 和 geom_col(),其中geom_bar() 产生的柱状图映射是经过统计变换的(count, ..prop..);geom_col()是不经过统计变换的,代表的就是该分类变量的实际值。

2. 简单柱状图

ggplot() + geom_bar(data = mpg, aes(x = class), stat = "count")

以每个x在数据集中出现的总数为y轴。


bar_plot.png

排序

ggplot2中一般数据和视觉元素映射是分开的,如果需要对柱状图排序,就需要对数据进行排序处理。 数据排序 柱状图排序

data_sorted <- mpg %>% 
 group_by(class) %>% 
 summarise(count = n()) %>%
 mutate(class = fct_reorder(class, count))
​
ggplot() + geom_bar(data =data_sorted, aes(x = class, y = count), 
 stat = "identity")
bar_plot.png

外框颜色和填充颜色

ggplot() + geom_bar(data = mpg, aes(x = class), stat = "count", 
fill = "white", colour="dodgerblue")

参数color控制外框颜色,fill控制填充颜色。
bar_plot.png

坐标轴中断

当柱状图非常高,展示时可以选择截断坐标轴,形成只有底部和上部的中断柱状图

Graph with broken y axis.png

水平柱状图

当数据分组标签名字过长时,有一种方法是将label旋转,这样它们就不会互相重叠。

film <- data.frame( 
 RANK =c(1,2,3,4,5),
 Title = c("Star Wars: The Last Jedi", 
 "Jumanji_Welcome to the Jungle", 
 "Pitch Perfect", 
 "The Greatest Showman",
 "Ferdinand"), 
 Weekend_gross = c(71565498, 36169328, 19928525, 805843, 7316746))
p <- ggplot() +  geom_bar(data = data_sorted, 
 aes(x = Title2, y = Weekend_gross2),
 stat = "identity",
 width = 0.5, 
 position = position_dodge(width = 0.9))
 p + theme(axis.text.x = element_text(angle = 45,
 vjust = 1,
 hjust = 1,
 size = 10),
 axis.text.y = element_text(size = 10))

但一般过长的名字,旋转后可读性也并不好,而且还破坏了整个图片中字符的水平排列一致性,所以比较好的解决办法是将坐标轴旋转( coord_flip()),生成水平柱状图。

library(tidyverse)
data_sorted <- film %>% 
 mutate(Title2 = fct_reorder(Title, Weekend_gross),
 Weekend_gross2 = Weekend_gross/1000000)
ggplot() +  geom_bar(data = data_sorted, 
 aes(x = Title2, y = Weekend_gross2),
 stat = "identity",
 width = 0.5, 
 position = position_dodge(width = 0.9)) + 
theme(panel.grid.major.x = element_line(colour = "black"), 
 panel.background = element_blank(),
 axis.line.y = element_blank(),
 axis.title.y = element_blank()) + 
 coord_flip()
img

误差线

  1. 标准差(sd)是描述性统计里用来表示数据本身均值范围的,两倍标准差范围以外就可能是异常值了,标准差的使用不牵扯均值对比推测,仅仅是描述性的。 2. 标准误(se)表示样本平均数对总体平均数的变异程度,反映抽样误差的大小,是量度结果精密度的指标。

: 95%置信区间是用的Mean ± 2*SE,即ci。

箱线图和柱状图的误差线

3. 堆叠柱状图

ggplot() + geom_bar(data = mpg, aes(x = class, fill = drv), stat = "count")

分组作图的默认position 是 position = "stack",fill参数表示将数据映射为填充颜色,color参数表示将数据映射为外框颜色。
bar_plot.png

堆叠组块间留空

利用lwd参数增加外框线宽度,然后将外框线颜色和背景色统一,就可以形成堆叠间有间隔的柱状图。

ggplot() + geom_bar(data = mpg, aes(x = class, group = drv, fill = drv), 
 stat = "count", lwd = 1.5, colour = "white") + 
 theme_classic()
bar_plot.png

百分比堆叠图

  1. 比较各组中每个类别出现次数在该组中占的百分比
ggplot() + geom_bar(data = mpg, aes(x = class, fill = factor(cyl)),
 position = "fill")
bar_plot.png
  1. 比较各组中每个类别实际值在该组中占的百分比
data <- mpg %>%
 group_by(class, cyl) %>% 
 summarise(count = n())
ggplot() + geom_bar(data =data, aes(x = class, y = count, fill = factor(cyl)),
 stat = "identity",
 position = "fill")
bar_plot.png

tips:由于数据集data中的count就是数据集mpg中每个组别的出现次数,因此值是图片是一样的。

堆叠柱状图连线

  1. 求出连线起点和终点坐标,用segment或line

  2. ggalluvial

4. 并排柱状图

position = "dodge"

ggplot() + geom_bar(data = mpg,aes(x = class, fill=factor(cyl)), position="dodge")

在aes()内部的width控制柱子的宽度,position = position_dodge()中的width控制的是一组中各柱子的间隔宽度。
bar_plot.png

position_dodge2()

2seater中的cyl在分组4,5和6上没有值,因此柱状图中2seater占据了x轴上4个位子的宽度。可以用position_dodge2解决, 其中的参数preserve = "single"使每个柱子宽度相同并居中,preserve = "total"结果与position_dodge相同。

ggplot() + geom_bar(data = mpg, aes(x = class, fill=factor(cyl)),
 position = position_dodge2(padding = 0,
 preserve = "single"))

position_dodge2中用参数padding控制同一分组中各柱子的间隔宽度,默认为padding = 0.1。
bar_plot.png

并排柱状图的误差线

并排的柱状图误差线和单个的相同,但需要注意一些参数。

  1. position_dodge() 用position_dodge() 产生的并排柱状图,首先,需要给误差线一个分组依据,然后进行的potion调试:
data <- mpg %>%
 group_by(class, cyl) %>% 
 summarise(count = n())
ggplot() + geom_col(data = data, aes(x = class, y = count, fill=factor(cyl)),
 position = position_dodge()) +
 geom_errorbar(data = data, aes(x = class,  ymin = count - 1, ymax = count + 1,
 group = factor(cyl)),
 width= 0.2,
 position = position_dodge(0.9))
bar_plot.png

由于width是根据柱子的宽度产生的,所以其宽度是不同的,我觉得应该有参数可以固定宽度,但是没有找到。

  1. position_dodge2() 同样的,position_dodge2()生成的并排柱状图,其error_bar()的position同样需要调试。
data <- mpg %>%
 group_by(class, cyl) %>% 
 summarise(count = n())

ggplot() + geom_col(data = data, aes(x = class, y = count, fill = factor(cyl)),
 position = position_dodge2(padding = 0, preserve = "single")) +
 geom_errorbar(data = data, aes(x = class, 
 ymin = count - 1,
 ymax = count + 1),
position = position_dodge2(padding = 0.5, preserve = "single"))
bar_plot.png

5. 棒棒糖图

a. 一个分组变量

data <- mpg %>%
 group_by( manufacturer) %>% 
 summarise(count = n())
​
# 设置连线的起点Y坐标为0
data$ymin <- rep(0, 15)
​
ggplot(data = data) + geom_point(aes(x = manufacturer, 
 y = count),size = 5) +
 geom_segment(aes(x = manufacturer, y = ymin,
 xend = manufacturer, yend = count)) +
# 设置y轴从0开始
 scale_y_continuous(expand = c(0,0))+
# 由于x轴名字有重叠,旋转坐标轴变成横向
 coord_flip() + 
 theme(panel.background = element_blank(), # 去掉背景格子
# 显示x平行网格线
 panel.grid.major.x = element_line(colour = "black"), 
# 显示x轴坐标
 axis.line.x = element_line(colour = "black"),
 axis.title.y = element_blank())
Lollipop Chart.png

[图片上传失败...(image-ae516e-1582459796851)]

b. 分组中再分组

data <- mpg %>%
 group_by( manufacturer, cyl) %>% 
 summarise(count = n())
data$ymin <- rep(0, times = 32)
# 将两个分组信息合并生成新的分组,此时
data$group <- paste(data$manufacturer, data$cyl, sep="_")
​
theme <- theme(panel.background = element_blank(), # 去掉背景格子
 # 显示x平行网格线
 panel.grid.major.x = element_line(colour = "black"), 
 # 显示x轴坐标
 axis.line.x = element_line(colour = "black"),
 axis.title.y = element_blank())
​
​
ggplot(data = data) + geom_point(aes(x = group, y = count, 
 color = factor(cyl)), 
 size = 5) +
 geom_segment(aes(x = group, y = ymin,
 xend = group, yend = count)) +
 scale_y_continuous(limits =c(0, 25) ,expand = c(0,0))+
 coord_flip() + theme
Lollipop_group.png

但x轴的labels就变成了合并后的文字,解决办法:

1.修改x轴信息

data <- mpg %>%
 group_by( manufacturer, cyl) %>% 
 summarise(count = n())
data$ymin <- rep(0, times = 32)
as.integer()
data$index <- as.integer(rownames(data))
​
theme <- theme(panel.background = element_blank(), # 去掉背景格子
 # 显示x平行网格线
 panel.grid.major.x = element_line(colour = "black"), 
 # 显示x轴坐标
 axis.line.x = element_line(colour = "black"),
 axis.title.y = element_blank())
​
​
ggplot(data = data) + geom_point(aes(x = index, y = count, 
 color = factor(cyl)), 
 size = 5) +
 geom_segment(aes(x = index, y = ymin,
 xend = index, yend = count)) +
 scale_y_continuous(limits =c(0, 25) ,expand = c(0,0)) + 
# 修改坐标轴信息
 scale_x_continuous(breaks = data$index, 
 labels = data$manufacturer) +
 coord_flip() + theme

2.对分组变量添加label信息

data <- mpg %>%
 group_by( manufacturer, cyl) %>% 
 summarise(count = n())
data$ymin <- rep(0, times = 32)
​
data$manufacturer <- factor(as.integer(rownames(data)), 
 labels = data$manufacturer)
​
theme <- theme(panel.background = element_blank(), # 去掉背景格子
 # 显示x平行网格线
 panel.grid.major.x = element_line(colour = "black"), 
 # 显示x轴坐标
 axis.line.x = element_line(colour = "black"),
 axis.title.y = element_blank())
​
​
ggplot(data = data) + geom_point(aes(x = manufacturer, y = count, 
 color = factor(cyl)), 
 size = 5) +
 geom_segment(aes(x = manufacturer, y = ymin,
 xend = manufacturer, yend = count)) +
 scale_y_continuous(limits =c(0, 25) ,expand = c(0,0)) + 
 coord_flip() + theme

3.structure() - Attributes信息

所有对象都可以具有任意其他属性。可以将它们视为该列表和命名列表构成的数据框。 可以使用attr()单独访问属性,也可以使用attribute()一次访问所有属性列表。而structure()函数是R中给对象赋予Attributes的函数。

  • names, character vector of element names

  • labels

  • class, used to implement the S3 object system, described in the next section

  • dim, used to turn vectors into high-dimensional structures

data <- mpg %>%
 group_by( manufacturer, cyl) %>% 
 summarise(count = n())
data$ymin <- rep(0, times = 32)
​
data$index <- fct_inseq(rownames(data))
# 添加Attributes - 也是labels
labels <- structure(data$manufacturer, 
 labels = data$index)
theme <- theme(panel.background = element_blank(), # 去掉背景格子
 # 显示x平行网格线
 panel.grid.major.x = element_line(colour = "black"), 
 # 显示x轴坐标
 axis.line.x = element_line(colour = "black"),
 axis.title.y = element_blank())
​
​
ggplot(data = data) + geom_point(aes(x = index, y = count, 
 color = factor(cyl)), 
 size = 5) +
 geom_segment(aes(x = index, y = ymin,
 xend = index, yend = count)) +
 scale_y_continuous(limits =c(0, 25) ,expand = c(0,0)) +
 scale_x_discrete(labels = labels) +
 coord_flip() + theme
Attributes.png

6. 金字塔图

金字塔图的核心就是找到需要分开的变量,然后以它为依据对数据进行正和负变换,然后将正负坐标轴强制设置成对应的正值。

set.seed(13)
data <- data.frame(num = rep(c(seq(from = 10, to = 100, by = 10),
 rev(seq(from = 40, to = 90, by = 10))), 
 times = 2),
 age = rep(seq(from = 80, to = 5, by = -5), 
 times = 2),
 gender = rep(c("male", "female"), each = 16))
​
# 根据性别对num赋值
data$num2 <- ifelse(data$gender == "male", 
 data$num *1,
 data$num * -1)
​
ggplot(data = data) + geom_col(aes(x = factor(age), 
 y = num2, 
 fill = gender)) + 
 scale_y_continuous(breaks = seq(from = -100, to = 100,
 by = 20),
 labels = c(seq(100, 0, -20), 
 seq(20, 100, 20))) + 
 coord_flip() + theme_bw()
pyramid.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容