在這個大數據的年代,想碰數據的人除了Excel之外,R語言幾乎是免不了要打交道的東西了。
在R語言資料視覺化的文章或教學中,GGplot2是極常被提及的套件。R語言內建有繪圖功能,但很多人認為GGplot2更加直覺好用(也可能更美觀,但我想這是見仁見智)。
GGplot2確實功能強大,但相關教學有些零碎。英語教學相當豐富,然而對於不善於英語的人來說,要搞清楚GGplot2的操作會是充滿挫折與壓力的過程。
初學GGplot2的時候,一直很希望有一種懶人模板,告訴我什麼指令會控制什麼就好,這樣我就複製貼上然後改一改就行了。當然有很多類似的文章,但往往缺乏一些我希望可以有的功能或者可以操作的物件。
東拼西湊的,終於完成了還算滿意的長條圖(與並列長條圖)。雖然距離摸熟GGplot還差得遠,但希望留下這些摸索的紀錄。
如果可以節省到誰的時間那就太好了。
本次所繪製的圖
先把本次做出來的圖放上來。
資料來源:文化部文化參與及消費調查,2016~2021年
以下會放上程式碼與code的解釋,要做類似的圖時可以根據需求自己稍作修改。
未來還有可能要做更細緻的圖,所以程式碼還有機會繼續更新以包含更多項目。
所用資料集
GGplot2所用的資料結構是data frame,由於這篇文章是針對ggplot2所寫,關於R語言如何操作data frame或者如何整理資料就不贅述。網路上已有相當豐富的中文資源,或者購買相關書籍也可以更完整的學習。
上面這張圖包含了三種數值:1. x軸的年齡類別 (共有11組)。2. y軸的人數比例。3. 區分淺綠色與深綠色的類別 (一年內是否去過博物館的人)。
以上三種數值都需要各自成為一個data frame中的欄位。以下為data frame的資料結構:
# 一個data frame,age為x軸,Freq為y軸,place_YesNo0為分組變數
#(不同顏色的長條)
# 這個資料集的名稱為ageDiff,主要用這個資料集來作圖
place_YesNo0 age Freq
1 0 1 5.07
2 1 1 6.39
3 0 2 8.22
4 1 2 12.15
5 0 3 7.79
6 1 3 9.94
7 0 4 7.44
8 1 4 9.01
9 0 5 7.74
10 1 5 10.86
11 0 6 8.16
12 1 6 11.17
13 0 7 8.32
14 1 7 9.27
15 0 8 9.58
16 1 8 8.55
17 0 9 9.74
18 1 9 6.97
19 0 10 10.46
20 1 10 6.84
21 0 11 17.48
22 1 11 8.86
# 另有一個資料集叫做ageDiff_n,這是各組的人數(N),也會用到
0 1
28323 22325
作圖程式碼與解釋
以下段落的撰寫方式是「程式碼解釋」對應後面的程式碼。因為這個筆記的目的是類似模板的功能,對於ggplot的基礎解釋就不會太多。
ggplot作圖,首先設定底層畫布。
指定資料集為ageDiff、對應於x、y軸的欄位、用來區分長條圖顏色 (fill) 的欄位。
小提醒:
視覺圖當中有許多種屬性,就是指例如x軸分組、顏色、大小、形狀等等的特性。
當我們把資料的欄位放在aes() 裡面時,就是要求ggplot根據某個欄位來繪製該屬性,這叫做mapping。
例如下方的意思就是:x軸請根據age欄位來畫 (那個as.factor的指令是將age轉換成類別資料),y軸請根據Freq欄位來畫,填色請根據place_YesNo0欄位來畫。
當這些屬性沒有放在aes()當中時,就不是mapping,而是直接指定該屬性的值 (看不懂這句可以直接跳過)。
ggplot(ageDiff,
aes(x = as.factor(age), y = Freq, fill = place_YesNo0)) +
要畫長條圖的話,用geom_col()指令。裡面的position參數設定為"dodge",繪製成並列長條圖。不設定的話,則會變成堆疊長條圖。
geom_col(position = "dodge") +
geom_text() 用來設定資料標籤 (就是每個長條上面的那些數值)。aes() 中的label是數值所對應的欄位(通常跟上面的y軸相同),col是用來設定要用什麼欄位來區分標籤顏色(通常跟上面的fill一樣,或者不特別設定col就是黑色)。
position一樣是要用dodge,但這裡用的是position_dodge() 的寫法,要指定width的數值。如果width是0,跟沒有dodge是一樣的意思,這時候兩組 (深、淺綠色) 的資料標籤就會重疊在一起。width越大,不同組之間的資料標籤錯開越多。設定為1是配合1080p的圖片設定的,需根據需要自行嘗試最適合的數值。
vjust是要在垂直位置上做調整,預設顯示位置會重疊於長條圖上緣,vjust為負值表示往上調整。同樣要自己嘗試怎樣的數值最適合。
size指的是標籤大小,預設是3.88,調成10比較適合1080p的圖。
geom_text(aes(label = Freq, col = place_YesNo0),
position = position_dodge(width = 1),
vjust = -0.2, size = 10) +
scale_x_discrete是拿來調整x軸的圖層。注意最後的discrete表示類別資料,在data frame裡面必須要是factor。
name是x軸的軸標題。
labels是要顯示在座標軸上的標記名稱。
小提醒:請記得順序務必要對應到資料中的factor排序,最好先用levels函數看一次factor的類別排序是如何。這部分需要熟悉factor資料類型,在這篇筆記裡面不會詳細解釋關於factor的操作。
scale_x_discrete(name = "年齡",
labels = c("15-19", "20-24", "25-29",
"30-34", "35-39", "40-44",
"45-49", "50-54", "55-59",
"60-64", "65 up")
) +
scale_y_continous是拿來調整y軸的圖層,大致上與x軸一樣,只是因為是連續變數,必須要用continous。
limits只能用在continous上,限制這個軸的上下限,必須是個長度為2的數值向量。
expand也必須是個長度為2的數值向量。如果用預設的方式畫圖,會發現x軸其實離長條有一點距離 (可以試試看把expand拿掉會發生什麼事?),把這個值設定為 c(0, 0) 就可以解決這問題。
小補充:expand其實是將軸「延伸」一段距離的意思,這個向量的第一個值是要延伸幾倍,第二個值是要延伸幾單位。不管怎樣,就是會讓x軸離長條圖有一段距離 (因為y軸被「延伸」了),所以長條圖看起來像是飛在空中一樣。同樣的設定在x軸也是適用的。
scale_y_continuous(name = "人數比例 (%)",
limits = c(0, 19),
expand = c(0, 0)
) +
scale_fill_是拿來修改fill圖層用的,後面接manual,和discrete的差別在於manual是要由使用者自己指定數值 (就是下面的values),但discrete會自己從對應 (mapping) 的資料欄位抓數值。
fill的數值 (value) 是什麼呢?就是不同組的長條圖要用什麼填色。下面的寫法是去抓RColorBrewer套件中,Paired調色板中的12個顏色,並指定要用第3到第4個顏色。不想這麼複雜的話其實直接用色碼或RGB的寫法就好 (範例附在程式碼後方)。
name和labels用法同上,不贅述。注意因為fill圖層是指「要用哪一個欄位來區分長條」,在圖上其實是類似一個分組變數的意思,所以這裡的labels實際上會是圖例的名稱。
小提示:有一種修改顏色的方法是使用scale_fill_brewer改。但這樣一來就不能用scale_fill_discrete修改圖例文字,因為scale_fill系列的圖層只能出現一個。本例使用manual的方式可以同時修改兩者。
scale_fill_manual(values = RColorBrewer::brewer.pal(12, "Paired")[3:4],
name = "一年內去過博物館",
labels = c(paste("否, N = ", ageDiff_n[1]),
paste("是, N = ", ageDiff_n[2])
)
) +
# 補充:
# paste()是連接字串的函數
# 色碼寫法範例如下,記得加引號、井字號,英文用小寫:
c("#ababab", "#8b7355")
# RGB寫法範例如下:
c(rgb(0, 0, 1), rgb(255, 0, 0) )
scale_color_則是為了修改color用的,因為前面的geom_text的顏色是color而不是fill,所以不會受到scale_fill_manual的影響。如果不設定color圖層,資料標籤的部分就會用預設的顏色顯示。
guide = NULL是指不要把這個圖層顯示成圖例,不寫這個參數就會多一組圖例出來。
(其實單純要修改text顏色的話,也可以把geom_text() 的col放在aes() 之外,並指定相應的顏色就可以了,就不需要特別用scale_color_manual來處理。)
scale_color_manual(values = RColorBrewer::brewer.pal(12, "Paired")[3:4],
guide = NULL) +
labs可以放圖表標題 (title)、副標題 (subtitle)、x和y軸標題 (x = "x name", y = "y name")、caption (就是範例圖右下角的文字) 等。
由於軸標題上面已經處理過了,這邊就不寫,只寫圖表標題和caption。
labs(title = "一年內有/無前往過博物館者的年齡分布",
caption = paste("N = ", sum(ageDiff_n))) +
theme就是拿來調整與資料無關的一些圖表元素
panel.grid系列是拿來處理x軸和y軸的格線,設定為element_blank()就是不要格線的意思。這一系列參數可以分為x軸、y軸,兩軸又可以各自分為主格線和副格線,各自由不同名稱的參數來控制。如果要調整線段顏色、粗細或類型,用element_line (color = "blue", size = 12, linetype = 1) 並更換"blue"、12、1即可。
panel.background是調整作圖區的背景,使用element_rect()來控制。
axis.title是軸標題、axis.text是軸上的標記、axis.line是軸線、axis.ticks是軸線上有一個小小的線段,會標記出資料點所在的位置。
legend系列就是控制圖例用的。
plot.title是控制圖表標題,face是拿來控制要粗體、斜體還是粗斜體,hjust是控制水平位置,0為置左、0.5為置中、1為靠右對齊。margin是設定標題的邊緣空間,用一個長度為4的數值向量設定上、右、下、左,並指定距離單位。
plot.caption是控制caption用的,那個plot.caption.position是指這個caption要在什麼範圍內對齊。指定"plot"就是在作圖區範圍對齊。
theme(panel.grid = element_blank(),
panel.background = element_rect(fill = "White"),
axis.title = element_text(size = 24),
axis.text.x = element_text(size = 20),
axis.line.x = element_line(linetype = 1),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
legend.title = element_text(size = 20),
legend.text = element_text(size = 16),
plot.title = element_text(size = 42, face = "bold", hjust = 0.5,
margin = margin(1, 0, 0, 0, "cm")),
plot.caption.position = "plot",
plot.caption = element_text(size = 16, hjust = 1)
)
以上是長條圖的模板,參數部分可以根據需求修改。想要更了解參數如何處理的話,善用help()可以得到更多資訊。
我也還在繼續了解ggplot2,可能有些地方並不是很正確,希望未來可以繼續修正。如果有什麼錯誤或者更好的寫法,歡迎留言多多交流~
不過單純的長條圖,也許用excel畫會比使用R還要更快一些。使用R來作圖應該是針對一些excel裡面很難畫出的圖形才是。
未來如果寫出其他類型的圖形範本,也會整理好筆記發成文章,但頻率就難以保證了。
可以參考的資源
這裡列出一些很好用的參考資源,不過是英文居多。
R語言中文教科書:
- R語言邁向Big Data之路──王者歸來(第二版),偏向從程式語言的角度切入,從0開始介紹R語言的操作與邏輯,相當完整。
一般來說,從統計的角度切入的R語言教科書結構都有點零散,時常讓人有知其然而不知其所以然的問題。這本書可以解決這個困擾。
- 統計就是這麼輕鬆R:AI幫你寫好資料分析,著重於R語言在行為科學上的應用,範圍涵蓋常見的行為科學資料分析方法(如t test、ANOVA等)。
對於R語言的基本操作著墨不多,但附有許多實用的程式碼工具,對於統計觀念的介紹完善並附有參考文獻。其中一章節專門講述ggplot2作圖套件,可以參考該章節的程式碼範例。