最近在寫深度學習系列文章時遇到了一些瓶頸, 不少統計分析結果和函數激活圖像都須要可視化顯示, 可是不太擅長這方面的相關技術, 因此先暫停理論知識更新, 準備用2天時間, 掌握一下基於R的ggplot2的可視化分析技術.git
圖形語法部分計劃寫的的大綱以下:算法
圖形語法由Wilkinson建立, 這裏不作形而上學的晦澀描述, 簡單來說, 圖形語法回答了"什麼是統計圖形"這一問題.express
那麼, 什麼是統計圖形?
一個圖形就是一種映射再加一些補充信息:app
幾個重要名詞的補充說明:
幾何對象: 點, 線, 多邊形;
標度: 數據取值映射到圖形空間;
統計變換: 對數據的某種彙總, 如數據分組計數建立直方圖;
分面: 繪圖窗口拆分紅多個子窗口, 也叫網格做圖.框架
注:
該小節只是對圖形與發的幾個名詞作了基本解釋, 後面將對ggplot2的圖形語法作深刻講解.ide
qplot()是ggplot2的一個入門級做圖函數, 意思是quick plot. 利用它可方便作出各類複雜圖形.
qplot和R的plot很像, 使用方法也差很少, 完整的參數列表可經過help(qplot)
或者?qplot
來獲取.函數
安裝tidyverse包並加載:工具
install.packages('tidyverse') library(tidyverse)
注意:
tidyverse是一個集合各類經常使用R包的綜合大禮包。安裝並library(tidyverse)
後, 默認導入如下包括ggplot2在內的多個依賴包:學習
# console output: ─────── Attaching packages ──────── ✔ ggplot2 2.2.1 ✔ purrr 0.2.4 ✔ tibble 1.3.4 ✔ dplyr 0.7.4 ✔ tidyr 0.7.2 ✔ stringr 1.2.0 ✔ readr 1.1.1 ✔ forcats 0.2.0
或者也能夠單獨安裝ggplot2:大數據
install.packages('ggplot2') library(ggplot2)
使用qqplot2自帶的diamonds
數據集.
建立一個小數據集:
set.seed(1000) dsmall <- diamonds[sample(nrow(diamonds), 100), ]
qplot() usage:
qplot(x, y = NULL, ..., data, facets = NULL, margins = FALSE, geom = "auto", xlim = c(NA, NA), ylim = c(NA, NA), log = "", main = NULL, xlab = deparse(substitute(x)), ylab = deparse(substitute(y)), asp = NA, stat = NULL, position = NULL)
require(ggplot2) set.seed(1410) dsmall <- diamonds[sample(nrow(diamonds),100),] qplot(carat, price, data=diamonds) # 注: carat, price是diamonds數據集的兩列, 分別映射到qplot()的x和y上
qplot(log(carat), log(price), data=diamonds) # 求log(carat)關於log(price)的關係
添加顏色:
qplot(carat, price, data=dsmall, colour=color)
添加形狀:
qplot(carat, price, data=dsmall, shape=cut, colour=color)
顏色, 形狀和大小都是圖形屬性的具體例子,每一個圖形屬性都對應了一個標度函數,將數據取值映射到圖形屬性的有效取值上, 如上圖, dsmall數據集中cut列每個取值都被映射成了一種散點形狀, 右側圖形標度除了各類顏色和圖形的映射關係.
使用透明度控制顏色和取值的映射, 能夠有效減輕圖形元素重疊現象, 使用alpha
的圖形屬性, 取值從0到1, 一般透明度用分數表示, 如1/10, 1/20, 分母表示重疊多少次後顏色將不透明:
qplot(carat, price, data=diamonds, alpha=(1/10))
gplot()經過改變幾何對象, 幾乎能夠畫出任何一種類型的圖形, 不一樣的幾何對象描述了數據展現的不一樣方式, 特別地, 有些幾何對象須要關聯相應的統計變換, 如頻率直方圖須要先分組計數再加上條形幾何對象.
常見的二維變量關係:
常見的一維分佈:
數據平滑曲線可用來展現大量數據點的某種趨勢, 能夠利用c()
函數將多個幾何對象組成向量傳給geom
, 幾何對象的堆疊順序和傳遞順序一致:
qplot(carat, price, data = diamonds, geom = c("point", "smooth")) qplot(carat, price, data = diamonds, geom = c("point", "smooth"), se = FALSE) # 不包含標準偏差
下圖展現了默認參數的的平滑曲線:
i) 包含標準偏差:
ii) 不包含標準偏差:
從平滑曲線中咱們能夠看出carat和price之間近似的指數關係;
ggplot內置了不少平滑器:
小數據集:
n<= 1000, 默認平滑器爲method = 'loess'
算法: 局部迴歸
取值: 曲線平滑程度由span參數控制,取值0(很不平滑)->1(很平滑)
大數據集
n>1000, Loess對大數據集並不合適(內存消耗O(n^2)), 此時使用的平滑器爲method = 'gam'
算法: formula = y ~ s(x)
調用mgcv包擬合一個廣義加和模型, 標準平滑公式: y~s(x, bs='cs')
線性擬合
擬合一條直線, method = 'lm', 也能夠經過formula = y ~ poly(x,2)
擬合一個二次多項式.
method = 'rlm'和前者相似, 可是更穩健, 對異常值不太敏感.
假設橫軸x = c('D','E','F','G','H','I','J')是一個包含7種顏色的分類變量, y是一個或多個連續變量.
經過箱線圖和擾動點圖能夠知道連續變量是如何隨着分類變量的變化而變化的:
擾動點圖:
qplot(color, price/carat, data = diamonds, geom = 'jitter', alpha = I(1/40))
箱線圖:
qplot(color, price/carat, data = diamonds, geom = 'boxplot', alpha = I(1/5))
總結:
直方圖
頻數直方圖:
qplot(carat, data = diamonds, geom = 'histogram')
密度直方圖:
qplot(carat, ..density.., data = diamonds, geom = 'histogram')
密度直方圖將數據分組求密度後映射到Y軸, 而頻數直方圖將數據分組計數後映射到Y軸.
分組(fill
)及平滑度(binwidth
)調整:
qplot(carat, data = diamonds, geom = 'histogram', binwidth=0.1, fill=color)
密度曲線
qplot(carat, data = diamonds, geom = 'density')
分組(colour
)及平滑度(adjust
)調整:
qplot(carat, data = diamonds, geom = 'density', adjust = 0.8, colour = color)
總結
頻率條形圖
qplot(color, data = diamonds, geom = 'bar')
按值加權條形圖
qplot(color, data = diamonds, geom = 'bar', weight = carat) + scale_y_continuous("carat")
注意:
上述兩圖縱座標不一樣,第一張圖展現了各顏色的頻率分佈, 第二張圖展現carat屬性的值在各類顏色上的加權和, 物理意義: 每種顏色的鑽石的總重量.
線條圖和路徑圖經常使用來可視化時間序列數據.
新數據集
ggplot2自帶economics數據集, 該數據集包含美國過去40年的經濟數據, 有時間變量.
線條圖
qplot(date, unemploy/pop, data = economics, geom = 'line')
上圖展現了失業率($unemploy/pop$)隨時間變化趨勢, 由於線條圖只能從左到右繪製, 故時間變化的方向被隱藏了.
路徑圖
經過路徑圖, 將年份映射到colour屬性上, 這樣便能看清楚時間的行進方向:
# 定義一個函數, 將字符串類型的date('1968-08-09')轉換成YYYY格式的數字(1968) year <- function(x) as.POSIXlt(x)$year + 1900 qplot(unemploy/pop, uempmed, data = economics, geom = c('point','path'), colour = year(date))
圖中uempmed是失業星期數取中位數, 表明了失業時長. 從圖中能夠看出, 失業率和失業時間是高度相關的, 且最近幾年(淺藍色), 相同的失業率下, 失業時長急劇增加.
比較不一樣分組的方法:
y軸變換
..density..
的形式告訴ggplot2將密度映射到y軸# Y軸:頻數 qplot(carat, data = diamonds, facets = color ~ ., geom = 'histogram', binwidth=0.1, xlim = c(0,3)) # Y軸:密度 qplot(carat, ..density.., data = diamonds, facets = color ~ ., geom = 'histogram', binwidth=0.1, xlim = c(0,3))
qplot()中默認分面方法: 經過row_var ~ col_var
建立一個圖形矩陣.
# 這裏咱們限制了下每一個子圖的橫軸範圍xlimi, 組距設置爲0.1 qplot(carat, data = diamonds, facets = color ~ cut, geom = 'histogram', binwidth=0.1, xlim = c(0,3))
圖示建立了一個行爲color, 列爲cut的圖形矩陣, 每一個分面的縱軸均爲鑽石重量carat.
只指定列, 不指定行
# 用.做爲row_var的佔位符 qplot(carat, data = diamonds, facets = . ~ color, geom = 'histogram', binwidth=0.1, xlim = c(0,3))
只指定行, 不指定列
qplot(carat, data = diamonds, facets = color ~ ., geom = 'histogram', binwidth=0.1, xlim = c(0,3))
座標軸區間
xlim, ylim控制, 例: xlim = c(0,20), ylim =c(-0.9, 0.9)
圖形標題
main控制主標題, xlab, ylab分別控制x軸和y軸的標籤(label), 這三個值均可以是字符串或者數學表達式
log
log是個字符型向量,log='x'表示x軸取對數, log = 'xy'表示x軸和y軸都取對數.
完整的示例:
qplot(carat, price/carat, data = diamonds, geom = 'point', xlim = c(.2, 1), # x軸顯示區間: 0.2~1.0 log = 'y', # log變換 xlab = 'Weight (carats)', # xlab: 字符串 ylab = expression(frac(price,carat)), # ylab: 數學表達式 main='Small diamonds' # 主標題: 字符串 )
ggplot2的圖層語法基於Wilkinson的圖形語法, 且在此基礎上添加了不少新功能.
要點
咱們要明白圖層語法的精髓--圖層語法給了咱們一個基本的做圖框架, 使咱們能夠從更高的視角審視圖形的構成,且每一個圖形組件均可以被修改.
咱們能夠按需添加所需圖形組件, 其它現存的圖形組件能夠繼續使用--在已有的幾何對象基礎上, 添加了新的統計變換後, 原有的幾何對象依然可使用.
下面將以以標準散點圖爲例, 來進一步解釋幾個核心概念:
qplot(carat, price, data = dsmall, colour = cut)
標度轉換
把數據單位(升, 英里/加侖等)轉換成可識別物理單位(像素, 顏色)的過程稱爲標度轉換(scaling).
標度轉換後的數據對於電腦是可識別的, 好比顏色用十六進制表示(#FF6C91), 大小, 形狀分別用數字和整數來表示, 下面的圖形屬性中將給出grid繪圖函數中(ggplot2底層使用了grid繪圖函數)的圖形屬性的基本標度轉換形式.
圖形屬性
在散點圖中, 每一個觀測數據都用一個點來表示, 點的位置有兩個變量的值來決定, 每一個點有橫座標, 縱座標, 還有大小, 顏色和形狀, 這些都稱爲圖形屬性.
總結一下, 圖形屬性的構成及grid繪圖函數中的表示方式:
注: 每一個圖形屬性都是一個常數或者變量, 是須要用數字填充的!!
幾何對象
幾何對象決定了圖形的類型, 舉例來說, 對於常見的只含一種幾何對象的圖, geom='point'時就是散點圖, geom='bar'則是條形圖.
常見的幾何對象:
注: 多種幾何對象組合而成的圖形每每沒有名字.
座標系統
常見的座標系統是笛卡爾座標系, 此外還有極座標和底圖中的球投影座標.
ggplot2在用繪圖系統的grid函數昨晚標度轉換後, 最後將根據數據點的值(x,y)來肯定其在途中的位置,此時由座標系統Coord來完成.
標度變換
標度變換在ggplot2繪圖過程當中很是重要, 包含多個步驟
在繪製複雜圖形時, 標度變換須要額外的步驟, 由於在添加了統計變換後,繪圖系統須要保證標度轉換多個數據集裏都是相同的.
好比以下包含多分面多圖層的複雜圖形:
qplot(displ, hwy, data = mpg, facets = .~year) + geom_smooth()
說明:
ggplot2繪圖過程包含以下幾步:
注意如下幾點:
標度(scale)控制數據到圖形屬性的映射, 每種標度都是一個數據空間定義域到圖形屬性空間值域的映射函數.
標度有兩項基本功能:
定義域
標度的定義域對應着該標度變量的取值範圍, 標度的定義域多是離散型或者連續型.
值域
標度的值域包含可感知的R能理解的圖形屬性:位置, 顏色,形狀, 大小, 線條類型. 標度的, 標度的值域也能夠是離散型或者連續型的.
定義域到值域的映射
1.變換(transformation)
只針對連續型定義域.如, 對數據取對數或開根號.變換完成後生成新的數據, 此後將對每一層作統一摘要, 摘要保證了變換後的圖形和變換前在線性尺度上一致.
2.訓練(training)
標度訓練主要完成標度的定義域計算.
對於單圖層原始數據圖形繪製中, 連續性變量,只須要獲得變換後數據最大值和最小值便可,離散型更簡單, 只須要列出全部不重複的類別性變量.
對對於橫跨多個數據集的多個圖層, 標度定義域計算將更復雜, 但本質上仍是統一各圖層的變量域, 保證最終畫到圖形上時, 各圖層的標度定義域一致.
定義域經過手動設置參數limits輸入時, 訓練過程將被跳過.
3.映射(mapping)
執行映射函數, 將標度的值域和訓練後的定義域數據映射到圖形屬性.
標度分位四組:
標度相關內容請參考R幫助文檔: ?scale_brewer
設置座標軸或者圖例上的標籤, 支持指定字符串或者數學表達式. 經常使用的輔助函數: xlab(), ylab(), labs()
默認標籤爲數據字段名:
p <- qplot(cty, hwy, data = mpg, colour = displ) p
注意x,y軸及圖例上的標籤均爲輸入數據字段名.
連續性數據位置標籤:
p <- qplot(cty, hwy, data = mpg, colour = displ) p + scale_x_continuous('City mpg') + scale_y_continuous('Highway')
xlab, ylab指定的標籤:
p <- qplot(cty, hwy, data = mpg, colour = displ) p + xlab('City labx') + ylab('Highway laby')
labs指定的標籤:
p <- qplot(cty, hwy, data = mpg, colour = displ) p + labs(x = 'city labx', y = 'Highway laby ', colour ='labcolour')
expression指定的標籤:
p <- qplot(cty, hwy, data = mpg, colour = displ) p + xlab(expression(frac(miles, gallon))) + ylab(expression(frac(miles, 'denom')))
固定標度的定義域, 連續性標度接受一個長度爲2的數值型向量如c(0.4, 5.2), 離散型標度接受一個字符型向量如c('red','black').
一旦設定了limits, 數據將不會進行任何訓練.
無limits:
p <- qplot(cyl, wt, data = mtcars, colour = drat) p
設定了limits:
p <- qplot(cyl, wt, data = mtcars, colour = drat) p + scale_x_continuous(limits = c(5.5, 6.5))
p <- qplot(cyl, wt, data = mtcars, colour = drat) p + scale_x_continuous(limits = c(5.5, 6.5)) + scale_colour_gradient(limits = c(4.0, 5.5))
控制座標軸或者圖例上哪些刻度線上的值應該顯示, 或者連續性標度在圖例上如何被分段, labels指定了斷點處顯示的標籤.
p <- qplot(cyl, wt, data = mtcars, colour = drat) p + scale_x_continuous(limits = c(5.5, 6.5)) + scale_colour_gradient(breaks = c(3.0,4.5))
若是沒有指定任何標籤, 將在每一個斷點處自動調用formatter()
來格式化生成標籤, 連續性標度的標籤刷爲comma, percent, dollar, scientific
, 離散型標度的標籤刷爲abbreviate
.
每張圖形有兩個位置標度: x標度和y標度. ggplot2提供連續性, 離散型(因子,字符,邏輯型向量)和日期型標度.
相關的輔助函數: xlim(), ylim()和lims()
標度舉例:xlim(10,20)
: 從10到20的連續型標度ylim(20,10)
: 20到10翻轉後的連續型y軸標度xlim("a","b","c")
: 離散型標度xlim(as.Data(c("2008-06-01","2008-04-01"))
: 日期型標度
連續型位置標度
常見: scale_x_continuous
和scale_y_continuous
每一個連續型標度均可接受一個trans參數, 裕興線性或非線性變化.
常見的變換器: asn($tanh^{-1}(x)$), exp, identity, log, log10, log2, logit, pow10, probit,, recip, reverse, sqrt
變換器經常使用來修改位置標度, 而且有漸變寫法:scale_x_continuous(trans='log10')
等價於scale_x_log10()
注意: 區分對標度變換和對數據變換是不一樣的, 即對數據取對數和對標度進行對數變換是不一樣的:
對數據變換:
qplot(log10(carat), log10(price), data = diamonds)
對標度變換:
qplot(carat, price, data = diamonds) + scale_x_log10()+ scale_y_log10()