1. 問(wèn)題描述
使用ggplot繪制柱狀圖時(shí),我們可能需要對(duì)柱進(jìn)行排序,例如,我們想探究看電視的平均時(shí)長(zhǎng)和宗教信仰之間的關(guān)系:
# 生成數(shù)據(jù)
relig_summary <- gss_cat %>%
group_by(relig) %>%
summarise(
age = mean(age, na.rm = TRUE),
tvhours = mean(tvhours, na.rm = TRUE),
n = n()
)
# 繪制
ggplot(relig_summary, aes(tvhours, relig)) + geom_col(width = .7, alpha = .7, color = "black")

由于柱子排布沒(méi)有明顯規(guī)律,所以圖非常難解讀。因此,我們期望對(duì)柱子排序進(jìn)行調(diào)整。
由于柱子排序,取決于Y軸上作為因子型變量的宗教順序,所以,我們可以調(diào)整relig的因子順序,也就是該變量的levels。
2. 解決方案
2.1 fct_reorder()
使用fct_reorder命令,它包含三個(gè)參數(shù):
-
f, 你希望調(diào)整順序的因子 -
x, 你希望用來(lái)調(diào)整順序的依據(jù)(必須是一個(gè)和f等長(zhǎng)的vector) -
fun, 如果x包含多個(gè)數(shù)值,你希望用何種方式處理他們,來(lái)對(duì)f進(jìn)行排序(默認(rèn)是median)。
使用該函數(shù),我們可以輕松的對(duì)柱狀圖按降序排列:
ggplot(relig_summary, aes(tvhours, fct_reorder(relig, tvhours))) +
geom_col(width = .7, alpha = .7, color = "black")

當(dāng)然,如果我們想讓上邊的柱子按升序排列,只需要在上邊的代碼中加一個(gè)負(fù)號(hào)-:
ggplot(relig_summary, aes(tvhours, fct_reorder(relig, - tvhours))) +
geom_col(width = .7, alpha = .7, color = "black")
2.2 fct_relevel()
有時(shí),我們需要將一個(gè)特殊的類別移到圖的最前邊作為參照,例如本案例中,我們特別想用“沒(méi)有信仰”的None和其他類型進(jìn)行對(duì)比,所以需要把None放在最前面,這時(shí)候可以用fct_relevel()命令:
# 先排序,再把`None`放在因子順序的最后
fct <- fct_reorder(relig_summary$relig, relig_summary$tvhours) %>%
fct_relevel("None", after = length(fct))
# 繪圖
ggplot(relig_summary, aes(tvhours, fct)) +
geom_col(width = .7, alpha = .7, color = "black")

其中fct_relevel("None", after = length(fct))的含義是將“None”放在第length(fct)位的后面,也就是第length(fct)-1的位次,對(duì)應(yīng)在圖中,就是最上方的位置。
如果想把"None"柱放在圖的最下邊,只需改寫(xiě)為after = 0就可以了。
2.3 fct_reorder2
有時(shí),我們需要基于兩個(gè)變量對(duì)某一因子進(jìn)行排序,特別是在繪制折線圖的時(shí)候,這時(shí)可以用到fct_reorder2命令,讓標(biāo)簽排序更加便于觀察:
# data
chks <- subset(ChickWeight, as.integer(Chick) < 10)
# Note that lines match order in legend
ggplot(chks, aes(Time, weight, colour = fct_reorder2(Chick, Time, weight))) +
geom_point() +
geom_line() +
labs(colour = "Chick")

2.5 fct_infreq() 和 fct_rev()
這兩個(gè)命令主要是搭配geom_bar()進(jìn)行使用的,同樣是對(duì)柱狀圖進(jìn)行排序:
# 升序
increase_plot <-
gss_cat %>%
mutate(marital = marital %>% fct_infreq() %>% fct_infreq()) %>%
ggplot(aes(marital)) +
geom_bar()
# 降序
decrease_plot <-
gss_cat %>%
mutate(marital = marital %>% fct_infreq() %>% fct_rev()) %>%
ggplot(aes(marital)) +
geom_bar()
# 合并
pacman::p_load(cowplot)
plot_grid(increase_plot, decrease_plot, labels = c('fct_infreq', 'fct_rev'), label_size = 12)
