数据准备
本示例数据是自编数据,仅为练习所用,数据结构假设为,两个年份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。
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") # 结果同上。
对于多分类柱状图,序列间会存在重叠(因为在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不调整。
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,让分组数据内序列间重叠部分显示出来。
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,让分组数据内序列间重叠部分显示出来。
- 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值对应数据绝对值。
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point() # 基础散点图。
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point(position = "stack") # 散点图,让点按分类堆叠。
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point(position = position_stack(vjust = 3)) # 散点图,stack,垂直堆叠放置,vjust参数调节。
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point(position = position_stack(reverse = T)) # 柱状图,stack,reverse = T。可以看出氮水平对应的分组变量数据的y值上下对调了。
- 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") # 基础柱状图。
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水平的数据占总数据的百分比。
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point() # 基础散点图。
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point(position = position_fill()) # 点图,position_fill()。
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point(position = position_fill(vjust = 5)) # 点图,position_fill(),vjust参数调整。
ggplot(data1, aes(x = nitrogen, y = v2, colour = variety)) + geom_point(position = position_fill(reverse = T)) # 点图,position_fill(),reverse参数调整。
- 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分组并排放置。
ggplot(data1, aes(x = nitrogen, y = v2, fill = variety)) + geom_col(position = position_dodge2()) # 柱状图,dodge2,按variety分组并排放置。
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。
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。结果同上,区别在于组别间有了分隔。
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,图柱重叠。
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组的图柱有重叠。
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调节图柱宽度。
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,图柱无间距,刚好挨着。
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。
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,图柱重叠。
ggplot(mtcars, aes(x = factor(carb))) + geom_bar(aes(fill = factor(vs)), position = position_dodge2(preserve = "total")) # 以自带数据集mtcars为例,preserve = total。
ggplot(mtcars, aes(x = factor(carb))) + geom_bar(aes(fill = factor(vs)), position = position_dodge2(preserve = "single")) # preserve = single。
- 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() # 绘制基本散点图结合箱线图。
ggplot(data1, aes(x = nitrogen, y = v2)) + geom_boxplot() + geom_point(position = position_jitter()) # 抖动调整。
ggplot(data1, aes(x = nitrogen, y = v2)) + geom_boxplot() + geom_point(position = "jitter") # 结果同上。
ggplot(data1, aes(x = nitrogen, y = v2)) + geom_boxplot() + geom_point(position = position_jitter(width = 0.1, height = 0.1)) # 调整抖动幅度。
ggplot(data1, aes(x = nitrogen, y = v2, fill = variety, colour = variety)) + geom_boxplot() + geom_point(position = position_jitterdodge(dodge.width = 0.1)) # 同时调整箱型图和抖动散点图的间距。
ggplot(data1, aes(x = nitrogen, y = v2, fill = variety, colour = variety)) + geom_boxplot() + geom_point(position = position_jitterdodge(dodge.width = 0.8)) # 同时调整箱型图和抖动散点图的间距。
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)) # 参数调整。
- 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)) # 散点图。
ggplot(data1, aes(x = v1, y = v2, colour = variety)) + geom_point(position = position_nudge(x = 2)) + xlim(c(0,4)) # x方向整体位移2个单位。
参考资料
- R Graphics Cookbook, 2nd edition,https://r-graphics.org/index.html
- ggplot2: 数据分析与图形艺术,西安交通大学出版社,2013.
- ggplot2 | 位置调整函数,https://zhuanlan.zhihu.com/p/409489632
- ggplot2绘图系统——位置调整函数,https://www.cnblogs.com/jessepeng/p/12307794.html
- R语言数据可视化之美:专业图表绘制指南,电子工业出版社,2019
- 关于位置调整(position adjustments),https://www.jianshu.com/p/23838a9d5470