Tidyverse自学笔记-ggplot2之位置调整

数据准备
本示例数据是自编数据,仅为练习所用,数据结构假设为,两个年份year(2020,2021),两个氮水平nitrogen(N1,N2),两个玉米品种variety(a,b)测定了5个试验指标(变量v1,v2,v3,v4,v5),每个处理3次重复block(1,2,3)。

library(tidyverse) # 调用tidyverse。
data1 <- read_csv(file = "data1.csv") # 导入数据。文档在工作目录下,所以直接给文件名导入。
data1 # 查看数据。
## # A tibble: 48 × 6
##     year nitrogen variety block    v1    v2
##    <dbl> <chr>    <chr>   <dbl> <dbl> <dbl>
##  1  2020 N1       a           1  1      4  
##  2  2020 N1       a           2  1.2    4.1
##  3  2020 N1       a           3  1.3    4  
##  4  2020 N1       b           1  1.08   4.5
##  5  2020 N1       b           2  1.05   3.8
##  6  2020 N1       b           3  1.15   3.5
##  7  2020 N2       a           1  1.32   3.2
##  8  2020 N2       a           2  1.28   4.2
##  9  2020 N2       a           3  1.35   3.7
## 10  2020 N2       b           1  1.33   4  
## # … with 38 more rows
## # ℹ Use `print(n = ...)` to see more rows

7.5 位置调整(position adjustments)

针对同一图层中的元素位置进行微调即为位置调整,多见于处理离散型数据,连续型数据一般很少出现完全重叠的问题。在geom_xxx()函数中,参数position表示绘图数据系列的位置调整,默认为"identity"(无位置调整),这个参数在绘制柱形图和条形图系列时经常用到,用来绘制簇状柱形图、堆积柱形图和百分比堆积柱形图等。除过“identity”,还包括stack、fill、dodge、jitter对应的位置设置。

  • position = position_identity():identity,不做任何位置调整,将每个对象直接显示在图中。ggplot2绘制散点图和折线图默认为identity。
ggplot(data1, aes(x = v1, y = v2)) + geom_point() + geom_line() # 散点图和折线图默认identity。
image.png
ggplot(data1, aes(x = nitrogen, y = v2)) + geom_bar(stat = "identity", position = position_identity())  # 柱状图,identity,不进行位置调整,绘制柱状图时,指定了stat = "identity"时,y值才能显示对应原始数据绝对值。
ggplot(data1, aes(x = nitrogen, y = v2)) + geom_bar(stat = "identity") # 结果同上。
image.png

对于多分类柱状图,序列间会存在重叠(因为在identity设置下,实际上每个分组内的序列图柱都是从0开始绘制,因此会造成重叠),为了让重叠部分能够显示出来,我们可以设置alpha参数为一个较小的数,从而使得条形略微透明;或者设定 fill = NA,让条形完全透明。

ggplot(data1, aes(x = nitrogen, y = v2, fill = variety)) + geom_bar(stat = "identity", position = position_identity(), width = 0.5, colour = "black") # 柱状图,identity不调整。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, fill = variety)) + geom_bar(stat = "identity", position = position_identity(), width = 0.5, alpha = 0.2, colour = "black")  # 设置alpha = 0.2,让分组数据内序列间重叠部分显示出来。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, fill = variety)) + geom_bar(stat = "identity", position = position_identity(), width = 0.5, fill = NA, colour = "black") # 设置fill = NA,让分组数据内序列间重叠部分显示出来。
image.png
  • position = position_stack():stack,垂直堆叠放置,对于分类柱状图,每个分类内的序列的图柱都是一个堆叠在另一个上面,图柱的高度代表此分类数据绝对值;柱形图和面积图的位置默认参数是stack。
    position_stack(vjust = 1, reverse = FALSE)
    vjust用于调节点或线垂直方向移动幅度。reverse若为TRUE,则会翻转堆叠顺序。
ggplot(data1, aes(x = nitrogen, y = v2, fill = variety)) + geom_bar(stat = "identity", position = "stack")  # 柱状图,stack,垂直堆叠放置,y值对应数据绝对值。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point() # 基础散点图。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point(position = "stack") # 散点图,让点按分类堆叠。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point(position = position_stack(vjust = 3))  # 散点图,stack,垂直堆叠放置,vjust参数调节。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point(position = position_stack(reverse = T))  # 柱状图,stack,reverse = T。可以看出氮水平对应的分组变量数据的y值上下对调了。
image.png
  • position = position_fill():fill,垂直堆叠放置,但每组堆叠条形具有同样的高度(将高度标准化为1),因此这种条形图可以非常轻松地比较各组间的比例,对应图形有百分比堆积面积图,百分比堆积柱形图等。
    position_fill(vjust = 1, reverse = FALSE)
    vjust用于调节点线垂直方向移动幅度。reverse若为TRUE,则会翻转堆叠顺序。
ggplot(data1, aes(x = nitrogen, y = v2, fill = variety)) + geom_bar(stat = "identity") # 基础柱状图。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, fill = variety)) + geom_bar(stat = "identity", position = position_fill(), width = 0.5)  # 柱状图,fill,垂直堆叠放置,y值对应百分比,图柱高均是1,里面variety水平用不同的颜色标识,图柱一个堆叠一个,每个图柱的高度代表这一nitrogen水平下对应variety水平的数据占总数据的百分比。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point() # 基础散点图。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point(position = position_fill()) # 点图,position_fill()。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point(position = position_fill(vjust = 5)) # 点图,position_fill(),vjust参数调整。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point(position = position_fill(reverse = T)) # 点图,position_fill(),reverse参数调整。
image.png
  • position = position_dodge():dodge,避免重叠,并排放置,将每组中的条形依次并列放置,这样可以非常轻松地比较每个条形表示的具体数值,对应图形有簇状柱形图。
    position_dodge(width = NULL, preserve = c("total", "single"))

position_dodge2()是position_dodge()的升级版。
position_dodge2(width = NULL, preserve = c("total", "single"), padding = 0.1, reverse = FALSE)

width:调节组距。position_dodge()中width调节的是组别并排之间的距离,默认值是0.9,当width大于0.9时后一组别向右偏移设定的幅度,小于0.9时,向左偏移设定的幅度。
preserve:调节并排后图形要素宽度。preserve ="total"表示各组的图形要素总宽度相等;preserve ="single"表示组间各单个图形要素的宽度相等。
padding:图柱间间距调节,默认为0.1,最大值取1。
reverse:是否翻转数据顺序。

ggplot(data1, aes(x = nitrogen, y = v2, fill = variety)) + geom_col(position = "dodge")  # 柱状图,dodge,按variety分组并排放置。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, fill = variety)) + geom_col(position = position_dodge2())  # 柱状图,dodge2,按variety分组并排放置。
image.png

dodge和dodge2的区别dodge2添加了组内间隔。那么为什么上面后一张图变了呢,我想是因为我用原始数据进行的绘图。下面看看数据求得平均值后的结果。

data1 %>% group_by(variety, nitrogen) %>% summarise(mean_v = mean(v1)) %>% ggplot(aes(x = nitrogen, y = mean_v, fill = variety)) + geom_bar(stat = "identity", position = position_dodge()) # dodge。
image.png
data1 %>% group_by(variety, nitrogen) %>% summarise(mean_v = mean(v1)) %>% ggplot(aes(x = nitrogen, y = mean_v, fill = variety)) + geom_bar(stat = "identity", position = position_dodge2()) # dodge2。结果同上,区别在于组别间有了分隔。
image.png
data1 %>% group_by(variety, nitrogen) %>% summarise(mean_v = mean(v1)) %>% ggplot(aes(x = nitrogen, y = mean_v, fill = variety)) + geom_bar(stat = "identity", position = position_dodge(width = 0.5)) # width小于0.9,图柱重叠。
image.png
data1 %>% group_by(variety, nitrogen) %>% summarise(mean_v = mean(v1)) %>% ggplot(aes(x = nitrogen, y = mean_v, fill = variety)) + geom_bar(stat = "identity", position = position_dodge(width = 1.2)) # width大于1.2,图柱有间距,因为width调节的是组间间距,因此b组整体向右偏移了1.2,但因为图柱宽度较宽,与a组的图柱有重叠。
image.png
data1 %>% group_by(variety, nitrogen) %>% summarise(mean_v = mean(v1)) %>% ggplot(aes(x = nitrogen, y = mean_v, fill = variety)) + geom_bar(stat = "identity", position = position_dodge(width = 1.2), width = 0.5) # 改变图柱宽度看看,可以看出dodge中的width调节组间间距,bar函数中的width调节图柱宽度。
image.png
data1 %>% group_by(variety, nitrogen) %>% summarise(mean_v = mean(v1)) %>% ggplot(aes(x = nitrogen, y = mean_v, fill = variety)) + geom_bar(stat = "identity", position = position_dodge2(padding = 0)) # padding取值等于0,图柱无间距,刚好挨着。
image.png
data1 %>% group_by(variety, nitrogen) %>% summarise(mean_v = mean(v1)) %>% ggplot(aes(x = nitrogen, y = mean_v, fill = variety)) + geom_bar(stat = "identity", position = position_dodge2(padding = 0.7)) # padding取值大于0,图柱有间距,取值越大,间距越大,但是最大值只能取到1。
image.png
data1 %>% group_by(variety, nitrogen) %>% summarise(mean_v = mean(v1)) %>% ggplot(aes(x = nitrogen, y = mean_v, fill = variety)) + geom_bar(stat = "identity", position = position_dodge2(padding = -0.7)) # padding取值小于0,图柱重叠。
image.png
ggplot(mtcars, aes(x = factor(carb))) + geom_bar(aes(fill = factor(vs)), position = position_dodge2(preserve = "total")) # 以自带数据集mtcars为例,preserve = total。
image.png
ggplot(mtcars, aes(x = factor(carb))) + geom_bar(aes(fill = factor(vs)), position = position_dodge2(preserve = "single")) # preserve = single。
image.png
  • position = position_jitter():给点添加抖动,避免重合。
    position_jitter(width = NULL, height = NULL, seed = NA)
    width调节水平方向抖动幅度,height调节垂直方向抖动幅度;jitterdodge可实现抖动和并排的同时调节。position_jitterdodge(jitter.width = NULL, jitter.height = 0, dodge.width = 0.75, seed = NA),同样地,jitter.width是x方向抖动幅度,默认值为0.4,jitter.height为y轴方向抖动幅度,默认为0,dodge.width为x轴方式并排间距,默认为0.75。
ggplot(data1, aes(x = nitrogen, y = v2)) + geom_boxplot() + geom_point() # 绘制基本散点图结合箱线图。
image.png
ggplot(data1, aes(x = nitrogen, y = v2)) + geom_boxplot() + geom_point(position = position_jitter()) # 抖动调整。
image.png
ggplot(data1, aes(x = nitrogen, y = v2)) + geom_boxplot() + geom_point(position = "jitter") # 结果同上。
image.png
ggplot(data1, aes(x = nitrogen, y = v2)) + geom_boxplot() + geom_point(position = position_jitter(width = 0.1, height = 0.1)) # 调整抖动幅度。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, fill = variety, colour = variety)) + geom_boxplot() + geom_point(position = position_jitterdodge(dodge.width = 0.1))  # 同时调整箱型图和抖动散点图的间距。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, fill = variety, colour = variety)) + geom_boxplot() + geom_point(position = position_jitterdodge(dodge.width = 0.8)) # 同时调整箱型图和抖动散点图的间距。
image.png
ggplot(data1, aes(x = nitrogen, y = v2, fill = variety, colour = variety)) + geom_boxplot() + geom_point(position = position_jitterdodge(jitter.height = 4, jitter.width = 0.2, dodge.width = 1)) # 参数调整。
image.png
  • position = positon_nudge():position_nudge(x = 0, y = 0)
    x和y用于指定在x或y方向上的平移量。
ggplot(data1, aes(x = v1, y = v2, colour = variety)) + geom_point() + xlim(c(0,4)) # 散点图。
image.png
ggplot(data1, aes(x = v1, y = v2, colour = variety)) + geom_point(position = position_nudge(x = 2)) + xlim(c(0,4)) # x方向整体位移2个单位。
image.png

参考资料

  1. R Graphics Cookbook, 2nd edition,https://r-graphics.org/index.html
  2. ggplot2: 数据分析与图形艺术,西安交通大学出版社,2013.
  3. ggplot2 | 位置调整函数,https://zhuanlan.zhihu.com/p/409489632
  4. ggplot2绘图系统——位置调整函数,https://www.cnblogs.com/jessepeng/p/12307794.html
  5. R语言数据可视化之美:专业图表绘制指南,电子工业出版社,2019
  6. 关于位置调整(position adjustments),https://www.jianshu.com/p/23838a9d5470
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容