最近一周一直在出差,包括今天,比較忙,更新少,這幾天看了幾篇文章,都使用了箱線圖,這裡索性將 Base plot 語法的箱線圖畫法總結一下。
什麼是 boxplotboxplot 我們通常翻譯為箱線圖,最初來自於數學家 John Tukey,正式名稱為 「Box and Whisker Plot」,最初的目的是將其用於所謂的五數概括法(five numbers summary),我們直接上圖:
1boxplot(
2 airquality$Ozone,
3 horizontal = TRUE,
4 col = NA,
5 axes = FALSE
6)
7arrows(1.08, 1.1, 10, 1.4, code = 1)
8text(11, 1.43, "最小值", cex = 0.6)
9
10arrows(18.5, 0.79, 13.5, 0.55, code = 1)
11text(14.5, 0.55, "四分之一位點", cex = 0.6)
12
13arrows(31.87, 1.2, 61.87, 1.43, code = 1)
14text(65, 1.48, "中位數", cex = 0.6)
15
16arrows(63.63, 0.8, 90, 0.69, code = 1)
17text(93, 0.59, "四分之三位點", cex = 0.6)
18
19arrows(122.88, 1, 96.5, 1.24, code = 1)
20text(97, 1.3, "最大值", cex = 0.6)
21
22rect(
23 xleft = 130,
24 xright = 174,
25 ybottom = 0.8,
26 ytop = 1.2,
27 lty = 2
28)
29text(150, 0.75, "異常值", cex = 0.6)
這裡解釋一下:
boxplot 實際上是顯示的四分位數(IQR),我們分別用:
表示四分位數的各個間隔點,也就是四分之一位點,中位數,以及四分之三位點。
這裡的異常值(outlier)的定義則為:
我沒找到合適的數據,顯示左側的異常值,我又懶得造數,所以上圖只顯示了右側的異常值數據。在上面的最大最小值的標記位置需要注意,它們是在異常值不參與計算的情況下得到的,boxplot 也有一個參數,表示為 outline = TRUE 來顯示上圖中我們用虛線框框起來的異常值。
notch = TRUE
1boxplot(
2 airquality$Ozone,
3 horizontal = TRUE,
4 col = NA,
5 axes = FALSE,
6 notch = TRUE,
7 outline = FALSE
8)
9
10rect(
11 xleft = 24.4,
12 xright = 38.8,
13 ybottom = 1.198,
14 ytop = 1.398,
15 lty = 2
16)
17text(31.6,
18 1.498,
19 '中位數的 95% 置信區間',
20 cex = 0.6)
21
22rect(
23 xleft = 18.24,
24 xright = 63.55,
25 ybottom = 0.793,
26 ytop = 0.593,
27 lty = 2
28)
29
30text(40.9,
31 0.493,
32 '50% 的數據',
33 cex = 0.6)
notch 表示是否顯示中位數的 95% 置信區間,也就是上圖中自左至右的虛線框的長度範圍,而
這個虛線框的的長度則表示了 50% 數據的範圍。
按不同分組作圖例如,按月份顯示溫度數據(主要是不同季節溫差大):
1cls <- palette.colors(6)[2:6]
2airquality$Temp <- (airquality$Temp - 32) * 5 / 9
3
4boxplot(Temp~Month,
5 data = airquality,
6 col = cls,
7 border = 'brown'
8 )
如果實際的數據點並不多,那麼可添加實際的數據點:
1with(airquality,
2 {
3 Month <- as.factor(Month)
4 n_each = table(Month)
5 cls2 <- unlist(mapply(rep, cls, time = n_each))
6
7 boxplot(Temp~Month,
8 col = NA,
9 outline = FALSE)
10 points(Temp~Month, pch = 19, col = cls2)
11 }
12 )
當然,Base R 提供了另外的一個解決方案,除此以外,還可以使用小提琴形狀,優勢就是能夠體現數據點的分布:
1library(vioplot)
2with(airquality,
3 {
4 vioplot(Temp ~ Month,
5 col = "gray"
6 )
7 stripchart(
8 Temp ~ Month,
9 pch = 19,
10 # colors do not need rep,
11 # formula distribute them to each group
12 col = cls,
13 vertical = TRUE,
14 method = "jitter",
15 jitter = 0.02,
16 add = TRUE
17 )
18 })
stripchart 本身就是作為 boxplot 的另一種形式,還提供了數據點輕微的抖動功能,方便我們更好的查看數據點,而小提琴圖則比使用矩形圖更加直觀的反應點的分布情況,在某些情況下,更適合使用,ggplot2 提供了很方便的功能來實現這幅圖,但是我還是喜歡這種 Base R 的語法來實現。
排序功能很多時候我們希望對數據重新排序,例如從高到底或從低到高來實現圖形的有序排列,這個我們可以通過使用 reorder 對中位數排序後作圖來實現,例如:
1with(airquality,
2 {
3 q2 <- reorder(Month, Temp, median)
4 boxplot(Temp~q2,
5 col = cls,
6 border = 'brown'
7 )
8 }
9)
reorder對因子的重新排序非常方便,儘管這裡可能因為月份,並不適合這種形式,但是遇到確實需要這種排列方式的作圖,則很輕鬆可以實現。
boxplot 數據如同 hist 函數一樣,boxplot 同樣能返回作圖的數據使用方式很簡單,就是將作圖命名:
1x <- boxplot(Temp~Month, data = airquality)
2x
3
1## $stats
2## [,1] [,2] [,3] [,4] [,5]
3## [1,] 13.33333 19.44444 26.66667 22.22222 17.22222
4## [2,] 15.55556 24.44444 27.50000 26.11111 21.66667
5## [3,] 18.88889 25.55556 28.88889 27.77778 24.44444
6## [4,] 20.55556 28.33333 30.00000 31.38889 27.22222
7## [5,] 27.22222 33.88889 33.33333 36.11111 33.88889
8##
9## $n
10## [1] 31 30 31 31 30
11##
12## $conf
13## [,1] [,2] [,3] [,4] [,5]
14## [1,] 17.47001 24.43374 28.17945 26.28007 22.84185
15## [2,] 20.30777 26.67737 29.59833 29.27549 26.04704
16##
17## $out
18## [1] 18.33333 22.77778 23.33333
19##
20## $group
21## [1] 2 3 3
22##
23## $names
24## [1] "5" "6" "7" "8" "9"
$stats 表示 IRQ 的各個位點和極值(按列排序,R 的 array 基本原則),例如第一列表示五月的最小值,Q1, Q2, Q3 以及最大值
n 表示各個分組或者各個 box 的數據點的數量(不包含 NA)
conf 表示 notch 的上下限的極值
out 表示 outlier 異常值
group 並非表示簡單的分組,而是表示上面的 outlier 點中,各個點屬於哪個分組,例如第二分組一個 outlier,第三個分組兩個,所以此處數據為 2,3,3。
names 真正的各個分組的名字,也就是此處的月份
參考資料https://chartio.com/resources/tutorials/what-is-a-box-plot/#:~:text=A%20Box%20Plot%20is%20the%20visual%20representation%20of,%E2%80%9CFive%20Number%20Summary%E2%80%9D%20of%20any%20given%20data%20set
https://r-coder.com/boxplot-r/
https://www.datamentor.io/r-programming/box-plot/