諏圖系列(1): 簡單條形圖

歡迎關注天善智能,我們是專注於商業智能BI,人工智能AI,大數據分析與挖掘領域的垂直社區,學習,問答、求職一站式搞定!

對商業智能BI、大數據分析挖掘、機器學習,python,R等數據領域感興趣的同學加微信:tstoutiao,邀請你進入數據愛好者交流群,數據愛好者們都在這兒。

諏圖系列(1): 簡單條形圖

作者:厚縕,中觀經濟諮詢助理研究員,業餘數據科學愛好者。博客:houyun.xyz

何謂“諏圖”


關於R作圖的資料汗牛充棟,數不勝數,既有基於基礎graphics包的,也有基於ggplot2等高級繪圖系統包的,還有基於其它JavaScript庫封裝的動態可視化包的,各有各的優勢,也各有各的短板。總的來看,基礎R包的“紙筆模式”更靈活,可以根據繪圖思路在任何地方添加需要的圖形標記,好比武學中的“內功”,內功基礎紮實能快速修煉各路高深武功招式;高級繪圖包用戶調用函數更簡潔,實現特定類型的可視化可以做到一鍵出圖,類似於武學中的招式,入門更快,但精進變通不易。最近讀了Rahlf的Data Visualisation with R: 100 Examples,更是發現,利用基礎R包可以靈活做出(設計)多種類型的統計圖形,而高級繪圖系統實現同樣的效果並不會更簡潔,甚至是難以實現。因此,特地開通了“諏圖”專欄來記錄學習、復現該書中主要案例的過程。

“諏圖”本意是“周圖”,意味著計劃每週更新一篇文章來解釋說明原書中的案例圖的實現過程,同時警醒下我“ZH”、“CH”、“SH”、“ZI”、“CI”、“SI”不分的普通話。當然,“諏”也有商量、謀取之意,把學習的過程記錄下來,也是為了方便自己翻閱。

特別說明:本系列遵循了原書中的實現思路,但是代碼、字體部分根據個人使用習慣做了微小的調整。

簡單條形圖


先上效果圖,然後再解釋如何實現。要自己動手實現這個圖,須下載原書中提供的案例數據集。

諏圖系列(1): 簡單條形圖

圖形設備


這裡使用的是cairo_pdf圖形設備,背景色設置為grey98,圖形寬度為9英寸,高度為6.5英寸。Rstudio默認的自帶的圖形設備RStudioGD對很多圖形參數設置的兼容性不好,在交互繪圖中可能會出現各種小bug,只要不報錯,不妨等繪圖結束輸出為PDF文件後再查看效果。

1pdf_file 2cairo_pdf(bg = "grey98", pdf_file, width = 9, height = 6.5)

全局繪圖參數


R基礎繪圖系統依賴於全局繪圖參數設置,設置後的影響之後的所有繪圖輸出,因此最好的習慣是先用opar = par()存下當前全局繪圖參數,在繪圖結束後調用par(opar)恢復原設置。

  • omi = c(0.65, 0.25, 0.75, 0.75) 下、左、上、右外邊距分別為0.65英寸、0.25英寸、0.75英寸和0.75英寸。
  • mai = c(0.3, 1.5, 0.35, 0) 下、左、上、右外邊距分別為0.3英寸、1.5英寸、0.35英寸和0英寸。由於左側要標記條形名稱,所以增加了預留寬度。
  • mgp = c(3, 3, 0) 標題、座標軸標籤和座標軸距離繪圖區邊緣分別為3行、3行和0行,具體距離依賴於文本縮放比例。
  • family = 'Arial' 默認字體為Arial。
  • las = 1 座標軸標籤方向,“1”表示始終水平放置標籤。
1opar 2par(
3 omi = c(0.65, 0.25, 0.75, 0.75),
4 mai = c(0.3, 1.5, 0.35, 0),
5 mgp = c(3, 3, 0),
6 family = 'Arial',
7 las = 1
8)
9

讀取數據


原書數據集為.xlsx格式,故使用readxl包中的read_xlsx()函數進行數據讀取,按照Percent變量的增序排序。為簡化繪圖部分的代碼輸入,用attach()函數將ipsos數據綁定到全局環境上。

1library(readxl)
2library(dplyr)
3ipsos % arrange(Percent)
4attach(ipsos)

主圖及標籤


主圖調用barplot()函數繪製,賦值給y是為獲取每個條形的縱座標。第一個參數Persent為條形的高度向量,其餘參數:

  • names.arg = FALSE 不自動標記條形名稱(後面手動添加)。
  • horiz = TRUE 水平繪製條形圖,默認是FALSE。
  • border = NA 條形無邊框,默認是黑色邊框。
  • xlim = c(0, 100) 圖形X軸的範圍是0-100,好的條形圖要保證條形都從0開始
  • col = 'grey' 條形填充色為灰色。
  • axes = FALSE 不繪製座標軸。
1y2 100), col = "grey", axes = FALSE)
3

接下來為每個條形手動添加名稱,若條形表示德國(Germany)和巴西(Brazil),字體為黑體,其它的為正常字體。用for循環通過text()函數來繪製每個條形標籤。關鍵參數是xpd = TRUE,表示繪圖區域擴展到原設定的繪圖區外,當x(y)座標值在X(y)軸最小值左側(下方)時為負。水平放置的條形圖條形名稱一般沿縱座標軸對齊,因此設置adj = 1使條形名稱右對齊。

1font_name 2for (i in 1:length(Country)) {
3 text(x = -10, y = y[i], labels = Country[i], adj = 1, xpd = TRUE, cex = 0.85,
4 family = font_name[i])
5 text(x = -3.5, y = y[i], labels = Percent[i], adj = 1, xpd = TRUE, cex = 0.85,
6 family = font_name[i])
7
8}
9

主圖背景陰影


添加背景陰影除了美觀之外,另一個作用是輔助判斷每個條形的長度,作用相當於網格線。因此,對於水平放置的條形圖,應繪製垂直的陰影或網格線,對於垂直放置的條形圖,則相反。本例的背景陰影將X軸(0-100)分為五組,即0-20,20-40,40-60,60-80,80-100,並繪製相應的矩形,矩形填充色設置為半透明的淺藍色,同時相鄰兩個矩形填充色的透明度不同,保證能區別不同的矩形。

1xleft 2xright 3ybottom 4ytop 5col_name 6 rgb(191, 239, 255, 120, maxColorValue = 255))
7rect(xleft, ybottom, xright, ytop, col = col_name, border = NA)

特定條形高亮


特定條形高亮有兩種實現方案:一是在繪製條形圖時指定每個條形的col值;二是繪製需要高亮的條形覆蓋到主條形圖上。這裡採用了第二種方案,主要是第一種方案設置背景陰影時會覆蓋高亮條形,影響高亮效果。首先將德國、巴西之外的其它國家的條形高度設置為0,然後指定高亮顏色,為品紅色,最後繪製高亮條形圖,注意添加add = TRUE參數,將高亮條形疊加到原圖上。

1ger_bra 2
3col 4x2 5 100), col = col, cex.names = 0.85, axes = FALSE, add = TRUE)
6

其它細節圖形標記


用arrows()函數標記所有數據的均值線x = 45(注意圖中的16個國家並不是所有接受調查的國家),為了使均值線延伸到繪圖區域外,需要設置xpd = TRUE,這裡不需要繪製箭頭,所以參數length設置為0,為了美觀,均值線兩端額外添加了黑色裝飾線。

用text()函數添加輔助文本,第一、二條在均值線旁標記了該線名稱和取值,第三條在右上角標記了圖中所有值均為百分數。

用mtext()函數設置座標軸標籤、圖形主標題、副標題和數據來源。該函數用文本行數(line)控制到繪圖區的距離,用adj參數控制文本左右位置,0表示居左,1表示居右,0.5表示居中,其它位置依此計算。outer = TRUE讓標記的文本可以延伸到外邊距(omi設置的邊距)。

 1arrows(45, -0.5, 45, 20, lwd = 1.5, length = 0, xpd = TRUE, col = "skyblue3")
2arrows(45, -0.5, 45, -0.75, lwd = 3, length = 0, xpd = TRUE)
3arrows(45, 20, 45, 20.25, lwd = 3, length = 0, xpd = TRUE)
4text(39, 20, "Average", adj = 1, xpd = TRUE, cex = 0.65, font = 3)
5text(43, 20, "45", adj = 1, xpd = TRUE, cex = 0.65, font = 4)
6text(100, 20, "All values in percent", adj = 1, xpd = TRUE, cex = 0.65, font = 3)
7xlab 8mtext(xlab, at = xlab, 1, line = 0, cex = 0.8)
9
10mtext(""I Definitely Believe in God or a Supreme Being"", 3, line = 1.3, adj = 0,
11 cex = 1.2, family = "Times New Roman", outer = TRUE)
12mtext("was said in 2010 in:", 3, line = -0.5, adj = 0, cex = 0.9, outer = TRUE)
13mtext("Source: www.ipsos–na.com, Design: Stefan Fichtel, ixtract", 1, line = 1,

14 adj = 1, cex = 0.65, outer = TRUE, font = 3)

繪圖完畢後,記得調用par(opar)恢復原繪圖參數設置,並關閉圖形設備。

1par(opar)
2dev.off()
諏圖系列(1): 簡單條形圖

往期精彩

  • 畫ROC曲線的R包總結
  • shinydashboard與shiny_史上最全(二)
  • sparklyr 1.0發佈,有哪些新功能?
  • R語言中文社區2018年終文章整理(作者篇)
  • R語言中文社區2018年終文章整理(類型篇)
諏圖系列(1): 簡單條形圖


分享到:


相關文章: