沒有作到信雅達的能力和時間,結合 原文去粗取精。
BBC 的數據部門在 ggplot 的基礎上,結合自身業務開發了 bbplot 。利用 bbplot 能夠更加高效的建立供新聞出版使用的數據可視化圖表。同時 BBC 的數據部門還撰寫了本手冊供有興趣使用 bbplot 建立相似如下圖表的人使用:git
利用 pacman 的 p_load
函數一次載入全部須要使用的庫:github
# 本行代碼會未安裝 pacman 的時候安裝 pacman,若是已安裝則直接載入 if(!require(pacman)) install.packages("pacman") pacman::p_Load('dplr', 'tidyr', 'gapminder', 'ggplot2', 'ggalt', 'forcats', 'R.utils', 'png', 'grid', ' ggpubr', bbplot)
因爲 bbplot
沒有上傳到 CRAN,因此目前只能使用 devtools
安裝。ide
# 運行此行安裝 devtools 包👇 # install.packages('devtools') devtools::install_github('bbc/bbplot')
關於 bbplot
更詳細的信息能夠在官方 github 庫查閱,本文接下來也會詳細記錄此庫的大部分使用方法及相關函數。函數
本包有兩個函數:bbc_style()
和finalise_plot()
。佈局
bbc_style()
:此函數不須要傳入參數,會在建立完繪圖以後被添加至 ggplot 的繪圖流程中。這個函數的做用是建立 BBC 風格的字號、字體、顏色、標尺、邊距等組件,繪圖的風格是根據設計部門的推薦和反饋定製的。字體
須要注意的是折線圖中的線條或者條形圖📊中條形的顏色不禁 bbc_style()
函數定製,須要使用標準的 ggplot
繪圖函數指定。ui
下面的代碼展現了 bbc_style()
常規使用方式。例子自己是用 gapminder
包提供的數據繪製一個簡單的折線圖。spa
# 繪圖所使用的數據來自 gapminder 包 line_df <- gapminder %>% filter(country == "Malawi") # 繪圖 line <- ggplot(line_df, aes(x = year, y = lifeExp)) + geom_line(colour = "#1390A1", size = 1)+ geom_hline(yintercept = 0,size = 1)+ bbc_style()+ labs(title = "Living longer",subtitle = "Life expectancy in Malawi 1952-2007")
這就是 bbc_style()
實際完成的工做。本質上是調整了 ggplot2
的 theme
函數的參數。設計
舉個例子,第一個參數設置了標題的字形、字號、字體以及顏色。3d
## function () ## { ## font <- "Helvetica" ## ggplot2::theme(plot.title = ggplot2::element_text(family = font, ## size = 28, face = "bold", color = "#222222"), plot.subtitle = ggplot2::element_text(family = font, ## size = 22, margin = ggplot2::margin(9, 0, 9, 0)), plot.caption = ggplot2::element_blank(), ## legend.position = "top", legend.text.align = 0, legend.background = ggplot2::element_blank(), ## legend.title = ggplot2::element_blank(), legend.key = ggplot2::element_blank(), ## legend.text = ggplot2::element_text(family = font, size = 18, ## color = "#222222"), axis.title = ggplot2::element_blank(), ## axis.text = ggplot2::element_text(family = font, size = 18, ## color = "#222222"), axis.text.x = ggplot2::element_text(margin = ggplot2::margin(5, ## b = 10)), axis.ticks = ggplot2::element_blank(), ## axis.line = ggplot2::element_blank(), panel.grid.minor = ggplot2::element_blank(), ## panel.grid.major.y = ggplot2::element_line(color = "#cbcbcb"), ## panel.grid.major.x = ggplot2::element_blank(), panel.background = ggplot2::element_blank(), ## strip.background = ggplot2::element_rect(fill = "white"), ## strip.text = ggplot2::element_text(size = 22, hjust = 0)) ## } ## <environment: namespace:bbplot>
能夠經過修改或添加 theme
函數的參數來調整圖表樣式。不過必定要在調用了 bbc_style()
以後再調用theme()
,不然的話 bbc_style()
會覆蓋掉你的調整。
下面的代碼會給圖片添加網格線:
theme(panel.grid.major.x = element_line(color = "#cbcbcb"), panel.grid.major.y = element_blank())
添加完bbc_style()
後還須要一步操做纔可讓你的圖表能夠公佈。finalise_plot()
可以使圖表的標題和副標題左對齊、添加信息來源、在圖表右下腳添加照片。它還能將圖表保存至指定的位置。這個函數有5個參數:
finalise_plot(plot_name, source, save_filepath, width_pixels = 640, height_pixels = 450)
plot_name
: 圖表的名字。好比上面繪製的表格 plot_name
是 "line"
。source
:須要在圖表左下角暫時的來源文字,須要在文字前先打上 "Source:",好比 `source = "Source: ONS"。svae_filepath
:圖表的保存路徑,須要包括.png
後綴。width_pixels
:默認 640 px。hieght_pixels
:,默認 450 px。logo_image_path
:指定在圖表右下角須要展現的 logo 保存的位置。默認是一個 png 格式的佔位文件,顏色和圖表的背景色同樣。若是你不須要展現 logo, 則無需調整此參數。當你想給圖表增長 logo 時,經過此參數指定 logo 的位置便可。finalise_plot(plot_name = my_line_plot, source = "Source: Gapminder", save_filepath = "filename_that_my_plot_should_be_saved_to.png", width_pixels = 640, height_pixels = 450, logo_image_path = "placeholder.png")
經過 finalise_plot()
函數,能夠在圖片發佈前作最後的微調並保存圖片。
由於 RStudio 的 plot 面板展現的圖表可能與最終保存的圖表不同,因此應該儘早保存並查看保存後圖表避免出錯。
因此,如何保存咱們以前繪製的圖表呢?
finalise_plot(plot_name = line, source = "Source: Gapminder", save_filepath = "images/line_plot_finalised_test.png", width_pixels = 640, height_pixels = 550)
#Prepare data line_df <- gapminder %>% filter(country == "China") #Make plot line <- ggplot(line_df, aes(x = year, y = lifeExp)) + geom_line(colour = "#1380A1", size = 1) + geom_hline(yintercept = 0, size = 1, colour="#333333") + bbc_style() + labs(title="Living longer", subtitle = "Life expectancy in China 1952-2007")
#Prepare data multiple_line_df <- gapminder %>% filter(country == "China" | country == "United States") #Make plot multiple_line <- ggplot(multiple_line_df, aes(x = year, y = lifeExp, colour = country)) + geom_line(size = 1) + geom_hline(yintercept = 0, size = 1, colour="#333333") + scale_colour_manual(values = c("#FAAB18", "#1380A1")) + bbc_style() + labs(title="Living longer", subtitle = "Life expectancy in China and the US")
#Prepare data bar_df <- gapminder %>% filter(year == 2007 & continent == "Africa") %>% arrange(desc(lifeExp)) %>% head(5) #Make plot bars <- ggplot(bar_df, aes(x = country, y = lifeExp)) + geom_bar(stat="identity", position="identity", fill="#1380A1") + geom_hline(yintercept = 0, size = 1, colour="#333333") + bbc_style() + labs(title="Reunion is highest", subtitle = "Highest African life expectancy, 2007")
#prepare data stacked_df <- gapminder %>% filter(year == 2007) %>% mutate(lifeExpGrouped = cut(lifeExp, breaks = c(0, 50, 65, 80, 90), labels = c("Under 50", "50-65", "65-80", "80+"))) %>% group_by(continent, lifeExpGrouped) %>% summarise(continentPop = sum(as.numeric(pop))) #set order of stacks by changing factor levels stacked_df$lifeExpGrouped = factor(stacked_df$lifeExpGrouped, levels = rev(levels(stacked_df$lifeExpGrouped))) #create plot stacked_bars <- ggplot(data = stacked_df, aes(x = continent, y = continentPop, fill = lifeExpGrouped)) + geom_bar(stat = "identity", position = "fill") + bbc_style() + scale_y_continuous(labels = scales::percent) + scale_fill_viridis_d(direction = -1) + geom_hline(yintercept = 0, size = 1, colour = "#333333") + labs(title = "How life expectancy varies", subtitle = "% of population by life expectancy band, 2007") + theme(legend.position = "top", legend.justification = "left") + guides(fill = guide_legend(reverse = TRUE))
這個例子中展現的是比例,有些時候須要展現準確的數字。只須要將 position = "fill"
修改成 position = "identity"
就行。
繪製分組條形圖和繪製條形圖的方法差很少,只須要將 position = "identity"
修改成 position = "dodge"
並設置 fill
便可。
#Prepare data grouped_bar_df <- gapminder %>% filter(year == 1967 | year == 2007) %>% select(country, year, lifeExp) %>% spread(year, lifeExp) %>% mutate(gap = `2007` - `1967`) %>% arrange(desc(gap)) %>% head(5) %>% gather(key = year, value = lifeExp, -country, -gap) #Make plot grouped_bars <- ggplot(grouped_bar_df, aes(x = country, y = lifeExp, fill = as.factor(year))) + geom_bar(stat="identity", position="dodge") + geom_hline(yintercept = 0, size = 1, colour="#333333") + bbc_style() + scale_fill_manual(values = c("#1380A1", "#FAAB18")) + labs(title="We're living longer", subtitle = "Biggest life expectancy rise, 1967-2007")
library("ggalt") library("tidyr") #Prepare data dumbbell_df <- gapminder %>% filter(year == 1967 | year == 2007) %>% select(country, year, lifeExp) %>% spread(year, lifeExp) %>% mutate(gap = `2007` - `1967`) %>% arrange(desc(gap)) %>% head(10) #Make plot ggplot(dumbbell_df, aes(x = `1967`, xend = `2007`, y = reorder(country, gap), group = country)) + geom_dumbbell(colour = "#dddddd", size = 3, colour_x = "#FAAB18", colour_xend = "#1380A1") + bbc_style() + labs(title="We're living longer", subtitle="Biggest life expectancy rise, 1967-2007")
hist_df <- gapminder %>% filter(year == 2007) ggplot(hist_df, aes(lifeExp)) + geom_histogram(binwidth = 5, colour = "white", fill = "#1380A1") + geom_hline(yintercept = 0, size = 1, colour="#333333") + bbc_style() + scale_x_continuous(limits = c(35, 95), breaks = seq(40, 90, by = 10), labels = c("40", "50", "60", "70", "80", "90 years")) + labs(title = "How life expectancy varies", subtitle = "Distribution of life expectancy in 2007")
有時候直接用文字註釋來識別數據會比圖例的效果更好。
使用 guides(colour = FALSE)
來刪除指定的元素。
multiple_line + guides(colours = FALSE)
也能夠一次性移除全部的圖例theme(legned.position = "none")
multiple_line + theme(legend.position ="none")
圖例默認展現在圖表的上方,可使用 legend.position = right/left/bottom
將圖例移動至其它位置:
mulitiple_line + theme(legend.position = "right")
若是須要精確指定圖例的位置,能夠給 legend.position
傳入座標參數。legend.position = c(0.98,0.1)
會將圖例移動至右下方。c(0,0)是左下角,c(1,0) 是右下角,c(0,1)是左上角。
若是想知道最終的圖表中圖例的實際位置,須要先經過finalise_plot()
函數將圖表保存後,查看實際的圖片。由於位置和圖片的大小有關。
multiple_line + theme(legend.position = c(0.115,1.05), legend.direction = "horizontal") + labs(title="Living longer", subtitle = "Life expectancy in China and the US\n")
若是想讓圖例左對齊,設置一個負邊距是比較簡單的辦法。語法是 margin(top, right, bottom, left)
,但這須要屢次保存和查看圖片來找到正確的數字。
+ theme(legend.margin = margin(0, 0, 0, -200)
經過調整 theme()
來刪除標題。記住,對 theme()
的全部修改都要放在bbc_style()
以後。
+ theme(legend.title = element_blank())
有時候須要調整圖例的順序,使得圖例和圖形的順序一致。
+ guides(fill = guide_legned(reverse = TRUE))
若是圖例特別多,出於美觀考慮,咱們可能須要對圖例從新佈局。
經過給 guides
傳遞參數能夠指定圖例的行數,下面的例子展現瞭如何建立一個共4行的圖例:
+ guides(fill = guide_legend(nrow = 4, byrow = T)
給 guides
傳入 override.aes
參數會在不影響原圖表的狀況下修改圖例的默認樣式。
+gides(fill = guide_legned(override.aes = list(size = 4)))
默認的 ggplot 圖例幾乎沒有間隙。能夠調整 scale labels manually 來增長間隙。
舉個例子:
若是你有一個圖形,顏色是根據數據來設置的,這時候你會有一個關於顏色的圖例。微調標籤就能調整圖例的間距:
+ scale_colour_manual(labels = function(x) paste0(" ",x," ")
若是你的圖例展現的信息有變化,上面的代碼也要相應做出修改。好比 fill,須要修改成 scale_fill_manual()
coord_flip()
能夠將橫座標修改成縱座標。
bars <- bars + coord_filp()
bbplot 默認只有水平網格線。若是要添加垂直網格線,能夠panel.grid.major.x = element_line
(一樣的,移除水平網格線panel.grid.major.y = element_blank()
)
bars <- bars + coord_flip() + theme(panel.grid.major.x = element_line(color="#cbcbcb"), panel.grid.major.y=element_blank()) ## 新添加的座標系會代替原有的座標系。
可使用 scale_y_continuous
或者 scale_x_continuous
任意修改座標軸標籤。
bars <- bars + scale_y_continuous(limits=c(0,85), breaks = seq(0, 80, by = 20), labels = c("0","20", "40", "60", "80 years")) bars
在指定座標軸標籤的同時,也指定了座標軸的區間(limits)。
經過 scale_y_continuous
能夠給座標軸標籤添加千位符號。第一種辦法是:
+ scale_y_continuous(labels = function(x) format(x, big.mark = ",", scientific = FALSE))
這個辦法有點麻煩。第二個辦法須要用到 scale
包,可是簡單點:
+ scale_y_cpntinuous(labels = scales::comma)
經過 scale_y_continuous
很容易作到:
+ scale_y_continuous(labels = function(x) paste0(x, "%")
比較麻煩的方法是使用scale_y_continuous
來指定繪圖範圍,可是若是不須要設置座標軸標籤的話,使用 xlim
或 ylim
就行:
bars + ylim(c(0,500))
默認的 theme 座標軸是沒有 title 的,不過能夠手工添加:
+ theme(axis.title = element_text(size = 18))
添加了座標軸 title 後,默認的 title 是變量名。能夠經過 labs()
修改成任意的 title。
+labs(x = "I'm an axis", y = "")
可使用axis.ticks.x
或者 axis.ticks.y
修改座標軸刻度:
multiple_line+ theme( axis.ticks.x = element_line(colour = "#333333"), axis.ticks.length = unit(0.26,"cm") )
最簡單的添加註釋的辦法是使用 geom_label
:
multiple_line + geom_label(aes(x = 1980, y = 45, label = "I'm an annotation!"),hjust = 0, vjust = 0.5, colour = "#555555", fill = "white", label.size = NA, family = "Helvetica", size = 6)
註釋準確的位置和 x
、y
參數以及文本對齊方式有關。
使用 \n
進行換行,使用 lineheight
設置行高。
multiple_line <- multiple_line + geom_label(aes(x = 1980, y = 45, label = "I'm quite a long\nannotation over\nthree rows"), hjust = 0, vjust = 0.5, lineheight = 0.8, colour = "#555555", fill = "white", label.size = NA, family="Helvetica", size = 6)
在咱們的案例中試一下:
multiple_line <- multiple_line + theme(legend.position = "none") + xlim(c(1950, 2011)) + geom_label(aes(x = 2007, y = 79, label = "US"), hjust = 0, vjust = 0.5, colour = "#1380A1", fill = "white", label.size = NA, family="Helvetica", size = 6) + geom_label(aes(x = 2007, y = 72, label = "China"), hjust = 0, vjust = 0.5, colour = "#FAAB18", fill = "white", label.size = NA, family="Helvetica", size = 6)
hjust
和 vjust
控制文本的水平和垂直對齊。它們的取值範圍爲 0 ~ 1。0 表示左(底部)對齊,1 表示右(頂部)對齊。
以上方法在添加文本標籤時頗有用,可是重複使用以上方法爲圖表添加註釋會讓工做變得很枯燥。
因此,若是你想給全部的數據點添加標籤,能夠直接根據數據來設置位置。
labelled.bars <- bars + geom_label(aes(x = country, y = lifeExp, label = round(lifeExp, 0)), hjust =1, vjust =0.5 colour = "white", fill = NA, label.size = NA, family = "Helvetica", size = 6) baelled.bars
上面的代碼自動給每一個國家都加上了文本標籤,免去了添加5次 geom_label
的麻煩。
若是你想給條形圖添加左對齊的標籤,只須要根據數據集設置 x
參數,而後專門直接設置y
參數就行。
labelled.bars.v2 <- bars + geom_label(aes(x = country, y = 4, label = round(lifeExp, 0)), hjust = 0, vjusy = 0.5, colour = "white", fill = NA, label.size = NA, family = "Helvetica", size = 6) labelled.bars.v2
有時候,須要從新排列條形的順序。爲了達到這個目的,須要在繪圖前設置數據的 factor levels。明確在繪製分類數據時想使用的順序。
dataset$column <- factor(dataset$column, levels = c("18-24","25-64","65+"))
這也能夠用於堆疊圖。
經過 ifelse()
能夠根據狀況設置 fill、alpha、size 等元素的值。
fill = ifelse(logical_condition, fill_if_true, fill_if_false)
ggplot(bar_df, aes(x = reorder(country, lifeExp),y =lifeExp))+ geom_bar(stat = "identify", position = "Identity", fill = ifelse( bar_df$country == "#Mauritius","#1380A1","#ddddddd"))+ coord_filp()+ labs(title = "Reunion is highest", subtitle = "Hightest African life expectancy, 2007")+ theme(panel.grid.major.x = element_line(color = "#cbcbcb"), panel.grid.major.y = element_blank())
(未完)