介紹如何使用 R 的 waffle
套件繪製鬆餅圖。
R 的 waffle
套件可以用來繪製鬆餅圖,以下是安裝與使用的教學。
waffle
套件先安裝一些相依性套件:
# 安裝相依性套件 install.packages(c("ggplot2", "RColorBrewer", "gridExtra", "gtable", "extrafont", "curl", "stringr", "htmlwidgets", "DT", "rlang", "dplyr"))
透過以下任一種方式安裝 waffle
套件:
# 安裝 waffle 套件(任選一種安裝方式即可) install.packages("waffle", repos = "https://cinc.rud.is") # 安裝 waffle 套件(任選一種安裝方式即可) devtools::install_git("https://git.rud.is/hrbrmstr/waffle.git") # 安裝 waffle 套件(任選一種安裝方式即可) devtools::install_git("https://git.sr.ht/~hrbrmstr/waffle") # 安裝 waffle 套件(任選一種安裝方式即可) devtools::install_gitlab("hrbrmstr/waffle") # 安裝 waffle 套件(任選一種安裝方式即可) devtools::install_bitbucket("hrbrmstr/waffle") # 安裝 waffle 套件(任選一種安裝方式即可) devtools::install_github("hrbrmstr/waffle")
載入 waffle
函式庫:
# 載入 waffle 函式庫 library(waffle)
若要繪製鬆餅圖,最簡單的方式就是將資料準備好,直接呼叫 walffle
函數來繪製:
# 測試資料 parts <- data.frame( names = c("basketball", "football", "volleyball"), vals = c(80, 30, 20) ) # 繪製鬆餅圖 waffle(parts, rows = 8)
waffle
本身有許多繪圖參數可以使用,例如設定每一排有幾個區塊、區塊間隔寬度、區塊顏色、說明文字位置等:
# 繪製鬆餅圖 waffle(parts, rows = 6, # 一排六個區塊 size = 1, # 區塊間隔寬度 colors = c("#969696", "#1879bf", "#009bda"), # 自定區塊顏色 legend_pos = "bottom" # 說明文字位置 )
若要繪製多張鬆餅圖,然後合併再一起進行比較,可以使用 iron
函數。
# 多張鬆餅圖比較 iron( waffle(c(thing1 = 72, thing2 = 28), rows = 5), waffle(c(thing1 = 25, thing2 = 75), rows = 5) )
這是一個比較完整的多張鬆餅圖比較範例:
# 第一張鬆餅圖 pain.adult.1997 <- c(`YOY (406)` = 406, `Adult (24)` = 24) A <- waffle( pain.adult.1997 / 2, rows = 7, # 一排七個區塊 size = 0.5, # 區塊間隔寬度 colors = c("#c7d4b6", "#a3aabd"), # 區塊顏色 title = "Paine Run Brook Trout Abundance (1997)", # 標題 xlab = "1 square = 2 fish", # X 軸標示文字 pad = 3 # 右方加入 3 個區塊寬度的空白,讓說明文字對齊 ) # 第二張鬆餅圖 pine.adult.1997 <- c(`YOY (221)` = 221, `Adult (143)` = 143) B <- waffle( pine.adult.1997 / 2, rows = 7, # 一排七個區塊 size = 0.5, # 區塊間隔寬度 colors = c("#c7d4b6", "#a3aabd"), # 區塊顏色 title = "Piney River Brook Trout Abundance (1997)", # 標題 xlab = "1 square = 2 fish", # X 軸標示文字 pad = 8 # 右方加入 8 個區塊寬度的空白,讓說明文字對齊 ) # 第三張鬆餅圖 stan.adult.1997 <- c(`YOY (270)` = 270, `Adult (197)` = 197) C <- waffle( stan.adult.1997 / 2, rows = 7, # 一排七個區塊 size = 0.5, # 區塊間隔寬度 colors = c("#c7d4b6", "#a3aabd"), # 區塊顏色 title = "Staunton River Trout Abundance (1997)", # 標題 xlab = "1 square = 2 fish" # X 軸標示文字 ) # 多張鬆餅圖比較 iron(A, B, C)
ggplot2
繪製鬆餅圖我們也可以使用標準的 ggplot
搭配 geom_waffle
來繪製鬆餅圖:
library(waffle) library(hrbrthemes) # 測試資料 parts <- data.frame( names = c("basketball", "football", "volleyball"), vals = c(80, 30, 20) ) # 以 ggplot 繪製鬆餅圖 ggplot(parts, aes(fill = names, values = vals)) + geom_waffle( color = "white", # 格線顏色 size = 0.8, # 區塊間隔寬度 n_rows = 6 # 每排六個區塊 ) + scale_x_discrete(expand = c(0, 0)) + # 去除 X 軸周圍空白 scale_y_discrete(expand = c(0, 0)) + # 去除 Y 軸周圍空白 ggthemes::scale_fill_tableau(name = NULL) + # 設定色盤 coord_equal() + # 設定 X 與 Y 軸等比例 labs( title = "Ball Games" # 設定標題 ) + theme_ipsum_rc(grid = "") + # 移除背景 theme_enhance_waffle() # 移除圖形上多餘的元件
以下是官方提供的範例,以 ggplot
繪製分組的鬆餅圖:
library(dplyr) library(waffle) # 準備資料 storms_df <- storms %>% filter(year >= 2010) %>% # 篩選 2010 年之後的資料 count(year, status) # 依據 year 與 status 統計資料比數 # 以 ggplot 繪製鬆餅圖 ggplot(storms_df, aes(fill = status, values = n)) + geom_waffle(color = "white", size = .25, n_rows = 10, flip = TRUE) + facet_wrap(~year, nrow = 1, strip.position = "bottom") + # 依據 year 分組 scale_x_discrete() + scale_y_continuous(labels = function(x) x * 10, # 設定乘數與 n_rows 相等 expand = c(0,0)) + ggthemes::scale_fill_tableau(name=NULL) + # 設定色盤 coord_equal() + # 設定 X 與 Y 軸等比例 labs( title = "Faceted Waffle Bar Chart", # 標題 subtitle = "{dplyr} storms data", # 子標題 x = "Year", # X 軸標示 y = "Count" # Y 軸標示 ) + theme_minimal(base_family = "Roboto Condensed") + # 設定使用 Roboto Condensed 字型 theme(panel.grid = element_blank(), axis.ticks.y = element_line()) + guides(fill = guide_legend(reverse = TRUE))
除了使用普通的方格之外,我們也可以使用 Font Awesome 5 字型來繪製鬆餅圖。
從 Font Awesome 5 的 GitHub 網站下載 fa-brands-400.ttf
、fa-solid-900.ttf
、fa-regular-400.ttf
三個 TTF 字型檔案,放在適當的位置。
如果不想手動下載 Font Awesome 5 的 TTF 字型檔案,也可以在安裝好 waffle
套件之後,使用其所提供的 install_fa_fonts()
從系統上直接取得 TTF 字型檔。
# 載入 waffle 函式庫 library(waffle) # 顯示 Font Awesome 5 字型檔案位置 install_fa_fonts()
若在 Linux 中,建議可以把 Font Awesome 5 的 TTF 字型放在 /usr/local/share/fonts
這個字型目錄之下,順便更新自己的字型庫,這樣系統上其他的軟體也可以使用(但在這裡的 R 中可以不需要):
# 更新字型庫 fc-cache -f -v
在 waffle
的官方文件中建議使用 extrafont
套件來安裝 Font Awesome 5 字型,但是我感覺 extrafont
並不是非常方便,因此這裡我們改用 showtext
套件來處理 Font Awesome 5 字型。
首先安裝好 showtext
套件並載入之後,使用 font_add
匯入自己下載的 TTF 字型檔案。除了 Font Awesome 5 字型之外,若要在繪圖時使用其他的字型(例如 Roboto Condensed),也可以一併在這裡匯入:
# 載入 showtext 套件 library(showtext) # 新增 Font Awesome 5 字型 font_add(family = "FontAwesome5Free-Solid", regular = "/usr/local/share/fonts/fa-solid-900.ttf") font_add(family = "FontAwesome5Free-Regular", regular = "/usr/local/share/fonts/fa-regular-400.ttf") font_add(family = "FontAwesome5Brands-Regular", regular = "/usr/local/share/fonts/fa-brands-400.ttf") # 新增 Roboto Condensed 字型 font_add("Roboto Condensed", regular = "/usr/local/share/fonts/RobotoCondensed-Regular.ttf") # 啟用 showtext showtext_auto()
這裡的三個 TTF 字型路徑請依照自己的狀況修改。
在設定好 Font Awesome 5 字型之後,我們就可以使用 Font Awesome 5 字型來畫圖了。
若以 waffle
函數直接繪圖,可以搭配 use_glyph
來指定 Font Awesome 5 的圖示名稱:
# 測試資料 parts <- data.frame( names = c("basketball", "football", "volleyball"), vals = c(17, 10, 5) ) # 以 waffle 繪製鬆餅圖 waffle(parts, rows = 3, # 每排三個區塊 colors = c("#969696", "#1879bf", "#009bda"), # 自定區塊顏色 use_glyph = "football-ball", # 自定 Font Awesome 5 圖示 size = 8 # 區塊間隔寬度 ) + expand_limits(y = c(0, 4))
圖示跟顏色一樣,可以根據不同的類型指定不同的圖示:
# 以 waffle 繪製鬆餅圖 waffle(parts, rows = 3, # 每排三個區塊 colors = c("#969696", "#1879bf", "#009bda"), # 自定區塊顏色 use_glyph = c("basketball-ball", "football-ball", "volleyball-ball"), # 自定 Font Awesome 5 圖示 size = 8 # 區塊間隔寬度 ) + expand_limits(y = c(0, 4))
若用 ggplot
的方式,可搭配 geom_pictogram
並以 scale_label_pictogram
與 scale_color_manual
來指定圖示與顏色:
# 測試資料 parts <- data.frame( names = c("basketball", "football", "volleyball"), vals = c(17, 10, 5) ) # 以 ggplot 繪製鬆餅圖 ggplot(parts, aes(label = names, values = vals, color = names)) + geom_pictogram(n_rows = 4) + # 以圖示繪製鬆餅圖 scale_color_manual( # 指定顏色 name = NULL, values = c( basketball = "#969696", football = "#1879bf", volleyball = "#009bda" ) ) + scale_label_pictogram( # 指定圖示 name = NULL, values = c( basketball = "basketball-ball", football = "football-ball", volleyball = "volleyball-ball" ) ) + coord_equal() + # 設定 X 與 Y 軸等比例 theme_ipsum_rc(grid="") + # 移除背景 theme_enhance_waffle() + # 移除圖形上多餘的元件 theme(legend.key.height = unit(2.25, "line")) + # 以下皆為圖形微調參數 theme(legend.text = element_text(size = 12, hjust = 0, vjust = 0.9)) + expand_limits(y = c(0, 5))
以下是用 ggplot
繪製分組的鬆餅圖,並自訂圖示的範例:
library(dplyr) library(waffle) # 準備資料 storms_df <- storms %>% filter(year >= 2010) %>% # 篩選 2010 年之後的資料 count(year, status) # 依據 year 與 status 統計資料比數 # 以 ggplot 繪製鬆餅圖 ggplot(storms_df, aes(label = status, values = n/5)) + geom_pictogram( n_rows = 4, # 一排四個區塊 size = 4, # 區塊大小 aes(colour = status), # 顏色對應 flip = TRUE # X 與 Y 軸對調 ) + scale_color_manual( # 指定顏色 name = NULL, values = c("#2f3640", "#273c75", "#718093"), labels = c("hurricane", "tropical depression", "tropical storm") ) + scale_label_pictogram( # 指定圖示 name = NULL, values = c("cloud-showers-heavy", "cloud", "cloud-rain"), labels = c("hurricane", "tropical depression", "tropical storm") ) + facet_wrap(~year, nrow = 1, strip.position = "bottom") + # 依據 year 分組 scale_x_discrete() + scale_y_continuous(labels = function(x) x * 10, # 設定乘數與 n_rows 相等 expand = c(0,0)) + ggthemes::scale_fill_tableau(name=NULL) + # 設定色盤 coord_equal() + # 設定 X 與 Y 軸等比例 labs( title = "Faceted Waffle Bar Chart", # 標題 subtitle = "{dplyr} storms data", # 子標題 x = "Year", # X 軸標示 y = "Count" # Y 軸標示 ) + theme_minimal(base_family = "Roboto Condensed") + # 設定使用 Roboto Condensed 字型 theme(panel.grid = element_blank(), axis.ticks.y = element_line()) + guides(fill = guide_legend(reverse = TRUE)) + theme(legend.key.height = unit(2.25, "line")) + theme(legend.text = element_text(size = 12, hjust = 0, vjust = 0.7))