【r<-包|繪圖】使用lattice進行高級繪圖

使用lattice進行高級繪圖是我之前在學習《R實戰(zhàn)》這本書少有涉及的章節(jié)之一浓瞪,在R里面懈玻,主要有兩大底層圖形系統(tǒng),一是base乾颁,二是grid涂乌。lattice與ggplot2正是基于grid構建,它們都有自己獨特的圖形語法英岭。我當前使用的主要是ggplot2湾盒,base畫圖基本不用,這里學習下lattice包并想后續(xù)深入學習繪圖的底層原理與實現(xiàn)诅妹。

內容:

  • lattice包介紹
  • 分組與調節(jié)
  • 在面板函數(shù)中添加信息
  • 自定義lattice圖形的外觀

這幾年開始學習R語言的估計對ggplot2要比lattice包熟悉很多罚勾,后者雖然在初學者中名聲不顯,但就憑lattice內置于R吭狡,而ggplot2要額外安裝來看尖殃,前者毫無疑問是被前輩們所廣泛使用的,這篇文章來正式學習一下划煮。

我們將一起學習Deepayan Sarkar(2008)編寫的lattice包送丰,它實現(xiàn)了Cleveland(1983,1993)提出的網格圖形。lattice包已經超越了Cleveland的初始可視化數(shù)據的方法弛秋,并且提供了一系列創(chuàng)建統(tǒng)計圖形的復雜方法器躏。

像ggplot2一樣,lattice圖形有它自己的語法蟹略,提供了對基礎圖形的替代方案登失,并且擅長繪制復雜數(shù)據。

lattice包

網格圖形能夠展示變量的分布或變量之間的關系挖炬,每幅圖代表一個或多個變量的各個水平揽浙。思考下面一個問題:紐約合唱團各聲部的歌手身高是如何變化的

lattice包在singer數(shù)據集中提供了這兩個變量的數(shù)據:

library(lattice)

histogram(~height | voice.part, data = singer, main = "Distribution of Heights by Voice Pitch",
          xlab = "Height (inches)")
img

從這幅圖可以看出,似乎男高音和男低音比女低音和女高音的身高更高捏萍。

在網格圖中太抓,調節(jié)變量的每個水平生成一個獨立的面板空闲。如果指定多個調節(jié)變量令杈,這些變量因子水平的每個組合都會生成一個面板(類似于ggplot2中的分面概念)。面板被分配到數(shù)組中以便于比較碴倾。在每個面板名為條帶的區(qū)域中會提供一個標簽逗噩。用戶可以控制每個面板上的圖形,條板的格式與放置的位置跌榔,面板的安排异雁,圖例的放置和內容以及其他許多的圖形特征。

lattice包提供了大量的函數(shù)來產生單因素圖(點圖僧须、核密度圖纲刀、直方圖、條形圖與箱線圖)担平,二元圖(散點圖示绊、條形圖、平行箱線圖)和多元圖(3D圖暂论、散點圖矩陣)面褐。每個高水平的畫圖函數(shù)都服從下面的格式:

graph_function(formula, data=, options)
  • graph_function 是下表的一個函數(shù)铸豁;
  • formula 指定要展示的變量和任意的調節(jié)變量球订;
  • data 指定數(shù)據框苏章;
  • options 是用逗號分隔的參數(shù)亡脸,用來調整圖形的內容颖杏、安排和注釋领突。

我們假定小寫字母代表數(shù)值型變量笋敞,大寫字母代表分類型變量(因子)观挎。高水平的畫圖函數(shù)通常采用的格式是:

y ~ x | A * B

其中豎線左側稱為主要變量觉痛,右邊的變量稱為調節(jié)變量役衡。

圖類型 函數(shù) 公式例子
3D等高線圖 contourplot() z~x*y
3D水平圖 levelplot() z~y*x
3D散點圖 cloud() z~x*y|A
3D線框圖 wireframe() z~y*x
條形圖 barchart() xA或Ax
箱線圖 bwplot() xA或Ax
點圖 dotplot() ~x|A
柱狀圖/直方圖 histogram() ~x
核密度圖 densityplot() ~x|A*B
平行坐標曲線圖 parallelplot() dataframe
散點圖 xyplot() y~x|A
散點圖矩陣 splom() dataframe
線框圖 stripplot() xA或Ax

為了盡快對lattice圖有一個認識,我們嘗試運行下面的代碼秧饮。里面的圖基于mtcars數(shù)據框中的汽車數(shù)據(里程映挂、車重、擋數(shù)盗尸、汽缸數(shù)等)柑船。

library(lattice)
attach(mtcars)

gear <- factor(gear, levels = c(3, 4, 5), 
               labels = c("3 gears", "4 gears", "5 gears"))
cyl <- factor(cyl, levels = c(4, 6, 8), 
              labels = c("4 cylinders", "6 cylinders", "8 cylinders"))

# 開始畫圖

densityplot(~mpg, main = "Density Plot", 
            xlab = "Miles per Gallon")
img
densityplot(~mpg | cyl,
            main = "Density Plot by Number of Cylinders",
            xlab = "Miles per Gallon")
img
bwplot(cyl ~ wt | gear,
       main = "Box Plots by Cylinders and Gears",
       xlab = "Miles per Gallon",
       ylab = "Cylinders")
img
xyplot(mpg ~ wt | cyl * gear, 
       main = "Scatter Plots by Cylinders and Gears",
       xlab = "Car Weight", ylab = "Miles per Gallon")

[圖片上傳失敗...(image-81350d-1528447963024)]

cloud(mpg ~ wt * qsec | cyl,
      main = "3D Scatter Plots by Cylinders")
img
dotplot(cyl ~ mpg | gear,
        main = "Dot Plots by Number of Gears and Cylinders",
        xlab = "Miles Per Gallon")
img
splom(mtcars[c(1:6)],
      main = "Scatter Plot Matrix for mtcars Data")
img
detach(mtcars)

其中ggplot2不能畫3D圖形,而lattice可以泼各。

lattice包中的高水平畫圖函數(shù)能產生可保存和修改的圖形對象鞍时,例如:

library(lattice)
mygraph <- densityplot(~height|voice.part, data=singer)

創(chuàng)建一個網格密度圖,并把它保存為對象mygraph,但是沒有圖形展示逆巍。使用plot(mygraph)將會顯示該圖及塘。

通過調整選項很容易更改lattice圖形,常見的選項列在下表中

選項 描述
aspect 指定每個面板圖形的縱橫比(高度/寬度)的一個數(shù)字
col锐极、pch笙僚、lty、lwd 分別指定在圖中使用的顏色灵再、符號肋层、線類型和線寬度的向量
group 分組變量(因子)
index.coord 列出展示面板順序的列表
key (auto.key) 支持分組變量中圖例的函數(shù)
layout 指定面板設置(列數(shù)與行數(shù))的二元素數(shù)值向量,如果需要翎迁,可以增加一個元素來表示頁面數(shù)
main栋猖、sub 指定主標題和副標題的字符向量
panel 在每個面板中生成圖的函數(shù)
scales 列出提供坐標軸注釋信息的列表
strip 用于自定義面板條帶的函數(shù)
split、position 數(shù)值型向量汪榔,在一頁上繪制多幅圖像
type 指定一個或多個散點圖繪圖選項(p=點蒲拉、l=線、r=回歸線痴腌、smooth=局部多項式回歸擬合雌团、g=網格圖形)的字符向量
xlab、ylab 指定橫軸和縱軸標簽的字符向量
xlim衷掷、ylim 指定橫軸和縱軸最小值辱姨、最大值的二元數(shù)值向量

我們可以在高級函數(shù)內部或者后面討論的面板函數(shù)內使用這些選項

我們也可以使用update()函數(shù)來調整lattice圖形對象戚嗅。

繼續(xù)歌手的例子:

plot(mygraph)
img
update(mygraph, col="red", pch=16, cex=.8, jitter=.05, lwd=2)
img

調節(jié)變量

通常情況下雨涛,調節(jié)變量是因子。但是對于連續(xù)的變量該如何操作呢懦胞?一種方式是使用R的cut()函數(shù)將連續(xù)的變量轉換為離散的變量替久,另一種方法是lattice包提供可以將連續(xù)變量轉換為名為shingle的數(shù)據結構。具體來說躏尉,連續(xù)變量被分成一系列(可能)重疊的范圍蚯根。

例如函數(shù)

myshingle <- equal.count(x, number=n, overlap=proportion)

將連續(xù)的變量x分成n個間隔,重疊的比例是proportion胀糜,每個間隔里的觀測值個數(shù)相同颅拦,并將其返回為變量myshingle。

一旦變量轉化為shingle教藻,就可以用它作為一個調節(jié)變量距帅。例如mtcars中的發(fā)動機排量是一個連續(xù)的變量,我們可以首先把它轉換為3水平的shingle變量:

displacement <- equal.count(mtcars$disp, number=3, overlap=0)

接下來把它應用到xyplot()函數(shù)中:

xyplot(mpg ~ wt|displacement, data = mtcars,
       main = "Miles per Gallon vs. Weight by Engine Displacement",
       xlab = "Weight", ylab = "Miles per Gallon",
       layout = c(3, 1), aspect = 1.5)
img

這里我們使用了選項來調整面板的布局(一行3列)和縱橫比(高/寬)來讓三組的對比變得更容易括堤。

下面我們學習面板函數(shù)來進一步自定義輸出碌秸。

面板函數(shù)

每一個高水平的畫圖函數(shù)都采用了默認的函數(shù)來繪制面板圖绍移。默認函數(shù)遵循命名規(guī)則panel.graph_function,例如

xyplot(mpg~wt|displacement, data=mtcars)

也可以寫成:

xyplot(mpg~wt|displacement, data=mtcars, panel=panel.xyplot)

這是一個強大的功能讥电,因為它可以讓我們用自己設計的默認函數(shù)來代替默認的面板函數(shù)蹂窖。我們也可以將lattice包50多個默認函數(shù)中的一個或者多個集成到我們自定義的函數(shù)中,自定義的面板函數(shù)在設計滿足我們需求的輸出時給了我們很大的靈活性恩敌。

下面我們來看些例子瞬测。

在前面,我們畫出了以汽車發(fā)動機排量為條件的汽車重量的油耗潮剪,如果你想要加上回歸線涣楷、地毯圖和網格線分唾,我們需要怎么做呢抗碰?

library(lattice)

displacement <- equal.count(mtcars$disp, number=3, overlap=0)

mypanel <- function(x, y){
    panel.xyplot(x, y, pch=19)
    panel.rug(x,y)
    panel.grid(h=-1, v=-1) # 添加水平和垂直的網格線
    panel.lmline(x, y, col="red", lwd=1, lty=2) # 添加回歸曲線
}


xyplot(mpg ~ wt|displacement, data=mtcars,
       layout=c(3,1),
       aspect=1.5,
       main = "Miles per Gallon vs. Weight by Engine Displacement",
       xlab = "Weight",
       ylab = "Miles per Gallon",
       panel = mypanel)
img

在第二個例子中,我們將畫出以汽車變速器類型為條件的油耗和發(fā)動機排量之間的關系绽乔。除了畫出自動和手動變速器發(fā)動機獨立的面板圖外弧蝇,我們還將添加擬合曲線和水平均值曲線

library(lattice)

mtcars$transmission <- factor(mtcars$am, levels=c(0,1), labels=c("Automatic", "Manual"))

panel.smoother <- function(x, y){
    panel.grid(h=-1, v=-1)
    panel.xyplot(x, y)
    panel.loess(x, y)
    panel.abline(h = mean(y), lwd = 2, lty = 2, col = "darkgreen")
}

xyplot(mpg~disp|transmission,data=mtcars,
       scales=list(cex=.8, col="red"),
       panel = panel.smoother,
       xlab = "Displacement", ylab = "Miles per Gallon",
       main = "MPG vs Displacement by Transmission Type",
       sub = "Dotted lines are Groups Means", aspect = 1)
img

分組變量

當你在lattice繪圖公式中增加調節(jié)變量時折砸,該變量的每個水平的獨立面板就會產生看疗。如果想添加的結果和每個水平正好相反,可以指定改變了為分組變量睦授。

比如說两芳,我們想利用核密度圖展示使用手動和自動變速器時汽車的油耗的分布:

densityplot(~mpg, data=mtcars,
            group=transmission,
            main="MPG Distribution by Transmission Type",
            xlab = "Miles per Gallon",
            auto.key = TRUE)
img

默認情況下,group=選項添加分組變量每個水平的圖去枷。值得注意的是怖辆,圖例和關鍵字不會在默認情況下生成,這里auto.key=TRUE創(chuàng)建一個基本圖例并把它放在圖的上方删顶。

下面實現(xiàn)更加自定義的圖形:

colors <- c("red", "blue")
lines <- c(1,2)
points <- c(16, 17)

key.trans <- list(title="Transmission",
                  space="bottom", columns=2,
                  text=list(levels(mtcars$transmission)),
                  points=list(pch=points, col=colors),
                  lines=list(col=colors, lty=lines),
                  cex.title=1, cex=.9)

densityplot(~mpg, data=mtcars,
            group=transmission,
            main="MPG Distribution by Transmission Type",
            xlab = "Miles per Gallon",
            pch=points, lty=lines, col=colors,
            lwd=2, jitter=.005,
            key=key.trans)
img

讓我們使用R自帶的CO2數(shù)據集討論一下在單個圖中包含分組和調節(jié)變量的例子竖螃。

這個數(shù)據集描述了12種植物在7種二氧化碳濃度下的二氧化碳吸收率。6種植物來自魁北克逗余,6種來自密西西比特咆。每個產地有3種植物在冷藏條件下研究,3種在非冷藏條件下研究录粱。在該例子中腻格,plant是分組變量,TypeTreatment是調節(jié)變量啥繁。

library(lattice)
colors <- "darkgreen"
symbols <- c(1:12)
linetypes <- c(1:3)

key.species <- list(title="Plant",
                    space = "right",
                    text = list(levels(CO2$Plant)),
                    points = list(pch=symbols, col=colors))

xyplot(uptake~conc|Type*Treatment, data=CO2,
       group=Plant,
       type="o",
       pch=symbols, col=colors, lty=linetypes,
       main = "Carbon Dioxide Uptake\nin Grass Plants",
       ylab = "Uptake",
       xlab = "Concentration",
       sub = "Grass Species: Echinochloa crus-galli",
       key = key.species)
img

圖形參數(shù)

lattice圖形不受par()函數(shù)的影響菜职,它使用的默認設置在一個大的列表對象中,可以通過trellis.par.get()函數(shù)獲得并通過trellis.par.set()函數(shù)更改输虱。我們可以使用show.settings()函數(shù)來直觀地展示當前的圖形設置些楣。

查看默認設置:

show.settings()
img

將它們保存到列表:

mysettings <- trellis.par.get()

可以使用names()查看列表成分:

names(mysettings)
##  [1] "grid.pars"         "fontsize"          "background"       
##  [4] "panel.background"  "clip"              "add.line"         
##  [7] "add.text"          "plot.polygon"      "box.dot"          
## [10] "box.rectangle"     "box.umbrella"      "dot.line"         
## [13] "dot.symbol"        "plot.line"         "plot.symbol"      
## [16] "reference.line"    "strip.background"  "strip.shingle"    
## [19] "strip.border"      "superpose.line"    "superpose.symbol" 
## [22] "superpose.polygon" "regions"           "shade.colors"     
## [25] "axis.line"         "axis.text"         "axis.components"  
## [28] "layout.heights"    "layout.widths"     "box.3d"           
## [31] "par.xlab.text"     "par.ylab.text"     "par.zlab.text"    
## [34] "par.main.text"     "par.sub.text"

修改:

mysettings$superpose.symbol$pch <- c(1:10)
trellis.par.set(mysettings)

查看更改:

show.settings()
img

自定義圖形條帶

面板條帶默認的背景是:第一個調節(jié)變量時桃紅色,第二個調節(jié)變量時淺綠色,第三個調節(jié)變量的淺藍色愁茁。我們可以使用上一節(jié)描述的方法蚕钦;或是加強控制,寫一個自定義條帶各方面的函數(shù)鹅很。

library(lattice)
histogram(~height | voice.part, data = singer,
          strip = strip.custom(bg="lightgrey",
                               par.strip.text = list(color="black", cex=.8, font=3)),
          main = "Distribution of Heights by Voice Pitch",
          xlab = "Height (inches)")
img

option=選項用來指定設定條帶外觀的函數(shù)嘶居,盡管我們可以從頭寫一個函數(shù)(參見?strip.default),但是改變一些設置并使用其他項的默認值更簡單促煮。strip.custom()函數(shù)可以幫助我們實現(xiàn)邮屁。bg選項控制了背景顏色,par.strip.text允許我們控制條帶文本的外觀菠齿。font選項可以分別取數(shù)值1佑吝、2、3绳匀、4芋忿,代表正常字體、粗體疾棵、斜體和粗斜體戈钢。

頁面布局

split選項將一個頁面分成指定數(shù)量的行和列,并把圖放到結果矩陣的特定單元格是尔。split選項的格式是:

split = c(x, y, nx, ny)

也就是在包括nx乘以ny個圖形的數(shù)組中殉了,把當前圖形放在x,y的位置,圖形的起始位置是在左上角拟枚。

library(lattice)

graph1 <- histogram(~height | voice.part, data = singer,
                    main = "Height of Choral Singers by Voice Part")
graph2 <- bwplot(height~voice.part, data = singer)
plot(graph1, split = c(1, 1, 1, 2))
plot(graph2, split = c(1, 2, 1, 2), newpage = FALSE)
img

我們可以更好的控制尺寸:

plot(graph1, position = c(0, .3, 1, 1))
plot(graph2, position = c(0, 0, 1, .3), newpage = FALSE)
img

這里的position=c(xmin, ymin, xmax, ymax)選項中薪铜,頁面的坐標系是x軸和y軸都從0到1的矩形,原點在左下角的(0,0)梨州。

我們還可以控制面板的順序

histogram(~height | voice.part, data = singer,
          index.cond = list(c(2, 4, 6, 8, 1, 3, 5, 7)))
img

深入學習

Deepayan Sarkar 的“Lattice Graphics: An Introduction”(http://mng.bz/jXUG, 2008)和Willian G.Jacoby的“An Introduction to Lattice Graphics in R” (http://mng.bz/v4TO, 2010)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末痕囱,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子暴匠,更是在濱河造成了極大的恐慌鞍恢,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件每窖,死亡現(xiàn)場離奇詭異帮掉,居然都是意外死亡,警方通過查閱死者的電腦和手機窒典,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門蟆炊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人瀑志,你說我怎么就攤上這事涩搓∥鄹眩” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵昧甘,是天一觀的道長良拼。 經常有香客問我,道長充边,這世上最難降的妖魔是什么庸推? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮浇冰,結果婚禮上贬媒,老公的妹妹穿的比我還像新娘。我一直安慰自己肘习,他們只是感情好际乘,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著井厌,像睡著了一般蚓庭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仅仆,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音垢袱,去河邊找鬼墓拜。 笑死,一個胖子當著我的面吹牛请契,可吹牛的內容都是我干的咳榜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼爽锥,長吁一口氣:“原來是場噩夢啊……” “哼涌韩!你這毒婦竟也來了?” 一聲冷哼從身側響起氯夷,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤臣樱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后腮考,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雇毫,經...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年踩蔚,在試婚紗的時候發(fā)現(xiàn)自己被綠了棚放。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡馅闽,死狀恐怖飘蚯,靈堂內的尸體忽然破棺而出馍迄,到底是詐尸還是另有隱情,我是刑警寧澤局骤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布柬姚,位于F島的核電站,受9級特大地震影響庄涡,放射性物質發(fā)生泄漏量承。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一穴店、第九天 我趴在偏房一處隱蔽的房頂上張望撕捍。 院中可真熱鬧,春花似錦泣洞、人聲如沸忧风。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽狮腿。三九已至,卻和暖如春呕诉,著一層夾襖步出監(jiān)牢的瞬間缘厢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工甩挫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留贴硫,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓伊者,卻偏偏與公主長得像英遭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子亦渗,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容