简介
箱线图,顾明思义,是形状像箱子并展示一组或多组数据分布的统计图,被认为是一个优于柱形图的数据可视化方案,文章中指出了很多箱线图的优点。
在ggplot2 中做箱线图的图形变换是geom_boxplot(),小提琴图是geom_violin。
可识别的美学映射?(geom_boxplot):
x
lower
upper
middle
ymin
ymax
alpha
colour
fill
group
linetype
shape
size
weight
详情参见vignette("ggplot2-specs"),直接在R中运行即可阅读。
箱线图(包含其变体小提琴图、Bean-plot)可以更真实的反应数据的分布,并且可以更轻松地在三个或更多样本之间进行比较。它使用25%,第50%和75%以及四分位数范围(IQR = Q3-Q1)来表征样本,其结果覆盖了中心数据的50%。 而且四分位数对异常值不敏感,并保留有关中心和差值的信息,加上异常值(outliers)的体现,使箱形图的内容更丰富。如果加上散点则可以更好的体现样品数,点越多,结果的稳定性、可靠性越好;而小提琴图(Violin plot)还可以通过箱体的宽窄在箱形图的基础上展示出数据分布的概率密度。
1. 简单箱线图
library(ggplot2)
ggplot(data = ToothGrowth) + geom_boxplot(aes(x = supp, y = len))
细节说明
首先看箱体:下边线代表下四分位数(第一四分位数,Q1),表示整体数据中有25%的数据少于该值;上边线代表上四分位数(第三四分位数,Q3),表示整体数据中有75%的数据少于该值;
箱体中间的线代表中位数,是一组数从小到大排列,居于正中间的单个数或正中间两个数的均值;
箱体的长度代表第三四分位数和第一四分位数的差值,也称为四分位间距(interquartile range,IQR);
箱体两端的衍生线最左延伸至Q1 - 1.5 x IQR(下极限),最右延伸至 Q3 + 1.5 x IQR(上极限);
超出上下极限线的点(或其他标记)表示潜在异常值(outliers)。
2. 水平箱线图
和其他图形一样,如果x轴上的label过长,一方面字体重叠影响阅读,另一方面旋转后破坏了图片中文字的一致性,显得不是很美观,最好就是生成水平箱线图。。
在原图的基础上,加上坐标轴旋转参数coord_flip()就可以了。
3. 分组
简单分组(fill, color)
在aes()里面添加fill 或者 color 参数。
ggplot(data = ToothGrowth) + geom_boxplot(aes(x = supp, y = len,
fill = factor(dose)))
3.箱线图与抖动图
加上散点则可以更好的体现样品数,点越多,结果的稳定性、可靠性越好。
ggplot(data = ToothGrowth) + geom_boxplot(aes(x = supp, y = len)) +
geom_jitter(aes(x = supp, y = len))
散点分组
当散点图也需要分组时,如果直接添加fill 和 color 就不够了,ggplot2 函数会分组混乱。
ggplot(data = ToothGrowth) +
geom_boxplot(aes(x = supp, y = len, color = factor(dose))) +
geom_jitter(aes(x = supp, y = len, color = factor(dose)))
解决办法
a. position_jitterdodge
ggplot(data = ToothGrowth) +
geom_boxplot(aes(x = supp, y = len, color = factor(dose))) +
geom_jitter(aes(x = supp, y = len, color = factor(dose)),
position = position_jitterdodge())
其他有趣的解法
b. 产生一个新的分组变量,使其同时包含两个分组信息。
在数据集中创建一个新的变量supp_dose,其值是将supp 和 dose粘贴到一起,这样新的一列数据就包含了两种分组信息。
ToothGrowth$supp_dose <- paste(ToothGrowth$supp, ToothGrowth$dose, sep="_")
# 然后以新的分组信息为x轴,代码不变。
ggplot(data = ToothGrowth) +
geom_boxplot(aes(x = supp_dose, y = len, color = factor(dose))) +
geom_jitter(aes(x = supp_dose, y = len, color = factor(dose)))
c. Interaction函数
b. 确实解决了上述问题,但坐标轴居然有6个,毕竟我们产生的新坐标系统确实包括6个不同的chr,interaction()base{}通过计算因子间关系产生可新的变量,可以
d. 移动所有点的坐标。
- 分组变量可以通过as.numeric()转化为连续数字变量:1,2,3,4,5,这样就生成了箱线图在x轴上的坐标。
as.numeric(factor(ToothGrowth$supp))
- 在此基础上,按照另一个分组变量获得一个索引。然后对每一组进行增加或者减少值,生成散点的x轴坐标。
as.numeric(factor(ToothGrowth$dose))
ToothGrowth$xpos <- as.numeric(factor(ToothGrowth$supp)) + c(- 0.25, 0, 0.25)[as.numeric(factor(ToothGrowth$dose))]
- 箱形图x坐标不变,散点图x坐标平移。
ggplot(data = ToothGrowth) +
geom_boxplot(aes(x = supp, y = len, color = factor(dose))) +
geom_jitter(aes(x = xpos, y = len, color = factor(dose)))
4.小提琴图(Violin plot)
5. raincloud = violin plot + boxplot + raw data
云雨图开始是一个咨询问答产物,连接直达源代码;yyplot里面有封装好的包。但是,有时候下载这个包可能会遇到安装不上的情况,所以没法下载的可以去问答界面拿源码自己打包一下。
箱线图离群值标签
return_outliers <- function(data, key){
p1 <- ggplot(data = data) + geom_boxplot(aes_string(y = key))
box_min <- ggplot_build(p1)[["data"]][[1]][["ymin"]]
box_max <- ggplot_build(p1)[["data"]][[1]][["ymax"]]
# selectting outliers
outliers <- subset(data, data[[key]] < box_min | data[[key]] > box_max)
return(outliers)
}
outliers <- return_outliers(mtcars, "mpg")
ggplot() + geom_boxplot(aes(y = mpg), outlier.colour = "red", data = mtcars) +
ggrepel::geom_label_repel(aes(x = 0, y = mpg, label = rownames(outliers)),
data = outliers)