【r<-高級|實戰|繪圖】ggplot2高級繪圖

以三個數據集解釋ggplot2的使用。第一個是lattice包中的singer數據集,它包括紐約合唱團歌手的高度和語音變量。第二個是mtcars數據集,它包含32輛汽車的詳細信息。最后一個是car包中的Salaries數據集,它包含大學教授的收入信息,并用來探索性別差異對它們收入的影響。這些數據集提供了各種可視化的挑戰。

ggplot2包介紹

在ggplot2中,圖是采用串聯起來(+)號函數創建的。每個函數修改屬于自己的部分。也就是說,每個函數完成圖中各個組件的相應功能,然后通過串聯+號將其連接起來,形成一個完整的圖形。

> library(ggplot2)
> ggplot(data=mtcars, aes(x=wt, y=mpg)) + 
+       geom_point() + 
+       labs(title="Automobie Data", x="Weight", y="Miles Per Gallon")
Scatter Plot between weight and miles of Cars.png

分解上述圖形的制作步驟:

? ggplot()初始化圖形并指定要用到的數據來源和變量。aes()函數的功能是指定每個變量扮演的角色(aes代表aesthetics,即如何用視覺形式呈現信息)。在這里,變量wt的值映射到x軸,mpg的值映射到y軸。

? ggplot函數設置圖形但沒有自己的視覺輸出。使用一個或多個幾何函數向圖中添加了幾何對象(簡寫為geom),包括點、線、條、箱線圖和陰影區域。在上述例子中,geom_point()函數在圖形中畫點,創建了一個散點圖。labs()函數是可選的,可以添加注釋、軸標簽、標題等。

ggplot2中有很多函數,并且大多數包含可選的參數。下面我們來看一下相應擴展。

> png('Scatter plot 2.png')
> ggplot(data=mtcars, aes(x=wt, y=mpg)) + 
+     geom_point(pch=17, color='blue', size=2) +
+     geom_smooth(method='lm', color='red', linetype=2) + 
+     labs(title="Automobile Data", x="Weight", y="Miles Per Gallon")
> dev.off()

![Uploading Automobile Data by Engine Type_988673.png . . .]

Scatter plot 2.png

我們依據對最初圖形的解釋,可以很清晰的觀察到不同的函數執行了什么樣的功能。

ggplot2包提供了分組和小面化的方法。分組指的是在一個圖形中顯示兩組或多組觀察結果。小面化指的是在單獨、并排的圖形上顯示觀察組。需要注意,ggplot2包在定義組或面時使用因子。

這里我們使用mtcars數據集查看分組和面,并進行繪圖。

Automobile Data by Engine Type.png
# 將變量轉換為因子
mtcars$am <- factor(mtcars$am, levels=c(0,1), labels=c("Automatic", "Manual"))
mtcars$vs <- factor(mtcars$vs, levels=c(0,1), labels=c("V-Engine", "Straight Engine"))
mtcars$cyl <- factor(mtcars$cyl)

library(ggplot2)
# 繪圖
ggplot(data=mtcars, aes(x=hp, y=mpg, shape=cyl, color=cyl)) + 
    geom_point(size=3) +
    facet_grid(am~vs) +
    labs(title="Automobile Data by Engine Type", x="Horsepower", y="Miles Per Gallon")

在本例中,amvs是刻度變量,cyl是分組變量。

用幾何函數指定圖的類型

ggplot()函數指定要繪制的數據源和變量,幾何函數則指定這些變量如何在視覺上進行表示。目前,有37個幾何函數可供使用。以下列出常用的函數。

函數 添加 選項
geom_bar() 條形圖 color, fill, alpha
geom_boxplot() 箱線圖 color, fill, alpha, notch, width
geom_density() 密度圖 color, fill, alpha, linetype
geom_histogram() 直方圖 color, fill, alpha, linetype, binwidth
geom_hline() 水平線 color, aplha, linetype, size
geom_jitter() 抖動點 color, size, alpha, shape
geom_line() 線圖 colorvalpha, linetype, size
geom_point() 散點圖 color, alpha, shape, size
geom_rug() 地毯圖 color, sides
geom_smooth() 擬合曲線 method, formula, color, fill, linetype, size
geom_text() 文字注解 這個非常多,參考相應文檔
geom_violin() 小提琴圖 color, fill, alpha, linetype
geom_vline() 垂線 color, alpha, linetype, size

關于幾何函數的常見選項

選項 詳述
color 對點、線和填充區域的邊界進行著色
fill 對填充區域著色,如條形和密度區域
alpha 顏色的透明度,從0(完全透明)到1(不透明)
linetype 圖案的線條(1=實線,2=虛線,3=點,4=點破折號,5=長破折號,6=雙破折號)
size 點的尺寸和線的寬度
shape 點的形狀(和pch一樣,0=開放的方形,1=開放的圓形,2=開放的三角形,等等)
position 繪制諸如條形圖和點等對象的位置。對條形圖來說,'dodge'將分組條形圖并排,'stacked'堆疊分組條形圖,'fill'垂直地堆疊分組條形圖并規范其高度相等。對于點來說,'jitter'減少點重疊。
binwidth 直方圖的寬度
notch 表示方塊圖是否應為缺口(TRUE/FALSE)
sides 地毯圖的安置("b"=底部, "l"=左部,"t"=頂部,"r"=右部,"bl"=左下部,等等)
width 箱線圖的寬度

下面舉個例子來驗證一下以上參數的使用:

data(Salaries, package='car')
library(ggplot2)
ggplot(Salaries, aes(x=rank, y=salary)) +
        geom_boxplot(fill="cornflowerblue",
                     color="black", notch = TRUE) +
        geom_point(position='jitter', color='blue', alpha=0.5) + 
        geom_rug(sides='l', color='black')
Salaries by Rank.png

該圖顯示了不同學術地位對應薪水的缺口箱線圖。實際的觀察值(教師)是重疊的,因而給予一定的透明度以避免遮擋箱線圖。它們還抖動以減少重疊。最后,一個地毯圖設置在左側以指示薪水的一般擴散。

當幾何函數組合形成新類型的圖時,ggplot2包的真正力量就會得到展示,讓我們利用singer數據集再來一探究竟。

library(ggplot2)
data(singer, package = "lattice")
ggplot(singer, aes(x=voice.part, y=height)) +
        geom_violin(fill="lightblue") + 
        geom_boxplot(fill="lightgreen", width=.2)
singer_combine_fig.png

箱線圖展示了在singer數據框中每個音部的25%,50%,75%分位數得分和任意的異常值。對于每個聲部身高范圍上的得分分布,小提琴圖展示了更多視覺線索。

接下來我們將使用幾何函數創建廣泛的圖表類型。讓我們從分組開始吧——在一個圖中展示多個分組觀察值。

分組

在R中,組通常用分類變量的水平(因子)來定義。

分組是通過ggplot2圖將一個或多個帶有諸如顏色、形狀、填充、尺寸和線條類型的視覺特征的分組變量來完成的。ggplot()聲明中的aes()函數負責分配變量(圖形的視覺特征)。

我們依舊以Salaries數據集來進行相關探索。

首先,查看薪水是如何隨學術等級變化的:

data(Salaries, package='car')
library(ggplot2)
ggplot(data=Salaries, aes(x=salary, fill=rank)) + 
        geom_density(alpha=.3)
Salaries density by Rank.png

接下來,我們通過性別和學術等級分組,繪制獲得博士學位年數和薪水的關系:

ggplot(Salaries, aes(x=yrs.since.phd, y=salary, color=rank, shape=sex)) +
        geom_point()
Salaries by phd.png

最后,我們可以用一個分組的條形圖按學術等級和性別來可視化教授的人數(三種條形圖方式):

Number by Rank1.png
Number by Rank2.png
Number by Rank3.png

值得注意的是,第三個圖形中y軸的標簽是錯誤的,它應該是比例而不是數量。我們可以通過添加y="proportion"參數到labs()函數來解決。

選項可以通過不同的方式使用,這取決于它們發生在aes()函數的內部還是外部。通常來說,變量應該設在aes()函數內,分配常數應該在aes()函數外

刻面

如果組在圖中并排出現而不是重疊為單一的圖形,關系就是清晰的。我們可以使用facet_wrap()函數和facet_grid()函數創建網格圖形(在ggplot2中也稱為刻面圖)。下表給出了相關的語法,var,rowvar,colvar是因子。

語法 結果
facet_wrap(~var, ncol=n) 將每個var水平排列成n列的獨立圖
facet_wrap(~var, nrow=n) 排成n行獨立圖
facet_grid(rowvar~colvar) rowvar和colvar組合的獨立圖
facet_grid(rowvar~.) 每個rowvar水平的獨立圖,配置成一個單列
facet_grid(.~colvar) 每個colvar水平的獨立圖,配置成單行

3個例子

data(singer, package = 'lattice')
library(ggplot2)
ggplot(data=singer, aes(x=height)) + 
        geom_histogram() +
        facet_wrap(~voice.part, nrow=4)

ggplot(data=singer, aes(x=height)) + 
        geom_density() +
        facet_grid(voice.part~., nrow=4)


data(Salaries, package='car')
library(ggplot2)
ggplot(Salaries, aes(x=yrs.since.phd, y=salary, color=rank, shape=rank))+
        geom_point() + facet_grid(.~sex)

添加光滑曲線

這一部分我們著重分析一下添加平滑曲線到散點圖的方法。

我們可以使用geom_smooth()函數來添加一系列的平滑曲線和置信區域。函數的參數參考下表:

選項 描述
method= 使用的平滑函數。允許的值包括lm, glm, smooth, rlm, glm,分別對應線性、廣義線性、loess、健壯線和廣義相加模型。smooth是默認值
formula= 在光滑函數中使用的公式。例子包括y~x, y~log(x), y~poly(x,n), y~ns(x)
se 繪制置信區間(TRUE/FALSE)默認為TRUE
level 使用的置信區間水平(默認為95%)
fullrange 指定擬合應涵蓋全圖(TRUE),或僅僅是數據(FALSE)。默認為FALSE

使用Salaries數據集,忽略性別和學術等級,我們先檢驗博士畢業年數和薪水之間的關系。

data(Salaries, package='car')
library(ggplot2)
ggplot(data=Salaries, aes(x=yrs.since.phd, y=salary)) +
        geom_smooth() + geom_point()
Salaries by yrs.png

統計函數

? ggplot2包中含有大量統計函數來計算所需的量,從而生產更多的可視化數據。通常情況下,幾何函數隱式地調用統計函數,我們不需要直接處理這些問題。不過指導它們的存在是有用的。

修改ggplot2圖形的外觀

R的基礎繪圖中,使用par()函數或特定的畫圖函數的圖形參數來自定義基本函數。遺憾的是,這些對ggplot2圖形沒有影響,該包提供了特定了函數來改變其圖形的外觀。

坐標軸

ggplot2包會自動生成基本所需要的圖形參數。當我們需要更大程度定制時,需要了解相應函數的用法。我們已經知道labs()函數可以用來添加標題并改變坐標軸標簽,讓我們再看看其他的有用函數:

函數 選項
scale_x_continuous()和scale_y_continuous() breaks=指定刻度標記、labels=指定刻度標記標簽、limits=控制要展示的值的范圍
scale_x_discrete()和scale_y_discrete() breaks=對因子的水平進行放置和排序,labels=指定這些水平的標簽,limits=表示哪些水平應該展示
coord_filp() 顛倒x軸和y軸

我們將這些函數應用一個分組箱線圖中,其中包含按學術等級和性別分組的薪資水平,代碼如下:

data(Salaries, package='car')
library(ggplot2)
ggplot(data=Salaries, aes(x=rank, y=salary, fill=sex)) +
    geom_boxplot() +
    scale_x_discrete(breaks=c('AsstProf', 'AssocProf', 'Prof'),
                     labels=c('Assistant\nProfessor',
                              "Associate\nProfessor",
                              "Full\nProfessor")) + 
    scale_y_continuous(breaks = c(50000, 100000, 150000, 200000),
                       labels=c('$50K','$100K','$150K','$200K')) + 
    labs(title="Faculty Salary by Rank and Sex", x='', y='')
Faculty Salary by Rank and Sex.png

圖例

圖例是指如何用顏色、形狀、尺寸等視覺特征表示數據特征的指南。標題和位置是最常用的定制特征。

當更改圖例的標題時,必須綜合考慮顏色、填充、尺寸等等。可以通過fill="mytitle"加到labs()函數中來改變標題。

標題的位置由theme()函數中的legen.position選項控制。可能的值包括left, top, right(默認), bottom。我們也可以在圖中給定的位置指定一個二元素向量。

使用添加修改上一個圖的代碼對圖形展示效果進行修改:

    labs(title="Faculty Salary by Rank and Sex", x='', y='',fill='Gender')
    theme(legend.position=c(.1,.8)) # 圖例的左上角分別距離左側邊緣10%,底部邊緣80%

標尺

ggplot2包使用標尺把數據空間的觀察值映射到可視化的空間中。標尺可以連續也可以離散。

在ggplot2中標尺的概念很普遍,可以通過查看以scale_開頭的函數來了解更多信息。

主題

主題可以讓我們控制這些圖的整體外觀。theme()函數中的選項可以讓我們調整字體、背景、顏色和網格線等。主題可以使用一次,也可以保存起來應用到多個圖中。嘗試探索以下代碼:

data(Salaries, package = 'car')
library(ggplot2)
mytheme <- theme(plot.title=element_text(face="bold.italic",
                                         size = "14", color = "brown"),
                 axis.title=element_text(face="bold.italic", size=10,
                                         color="brown"),
                 axis.text=element_text(face="bold", size=9,
                                        color="darkblue"),
                 panel.background = element_rect(fill="white",
                                                 color="darkblue"),
                 panel.grid.major.y=element_line(color="grey",
                                                 linetype = 2),
                 panel.grid.minor.y=element_line(color="grey",
                                                 linetype=2),
                 panel.grid.minor.x=element_blank(),
                 legend.position = "top")

ggplot(Salaries, aes(x=rank,y=salary,fill=sex)) +
        geom_boxplot() + 
        labs(title="Salary by Rank and Sex", x="Rank", y="Salary") +
        mytheme
mytheme.png

多重圖

? 基礎繪圖中,我們使用圖形參數mfrow和基本函數layout()把兩個或多個基本圖放到單個圖中,同樣,這種方法在ggplot2中不適用。將多個ggplot2包的圖形放到單個圖形中最簡單的方式是使用gridExtra包中的grid.arrange()函數。我們需要事先安裝這個包。

讓我們創建3個ggplot2圖并把它放在單個圖形中。

data(Salaries, package = 'car')
library(ggplot2)
p1 <- ggplot(data=Salaries, aes(x=rank)) + geom_bar()
p2 <- ggplot(data=Salaries, aes(x=sex)) + geom_bar()
p3 <- ggplot(data=Salaries, aes(x=yrs.since.phd, y=salary)) + geom_point()

library(gridExtra)
grid.arrange(p1,p2,p3,ncol=3)
multiple pic.png

注意截面圖(刻面圖)和多重圖的區別。

保存圖形

可以使用標準方法來保存創建的圖形,也可以使用ggsave()函數更方便保存它們。它的選項包括保存哪幅圖形,保存在哪里和以什么形式保存。例如

myplot <- ggplot(data=mtcars, aes(x=mpg)) + geom_histogram()
ggsave(file="mygraph.png",plot=myplot,width=5,height=4)

myplot保存為5英寸X4英寸PNG格式。我們可以通過設置文件拓展名為ps, tex, jpeg, pdf, tiff, png, bmp, svg, wmf來保存為不同格式。

如果忽略plot=選項,最近創建的圖形會被保存。更多細節參考help(ggsave)

參考:R實戰

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,310評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,566評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,055評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,303評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,799評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,683評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,899評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,135評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,528評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,844評論 2 372

推薦閱讀更多精彩內容

  • 簡介 文章較長,點擊直達我的博客,瀏覽效果更好。本文內容基本是來源于STHDA,這是一份十分詳細的ggplot2使...
    taoyan閱讀 51,309評論 7 159
  • 【感恩有你】20170717學習力踐行記錄D63 學習:復聽學習力第一課節父母教練修心營40分鐘,《孩子是如何學習...
    恩恩媽閱讀 226評論 0 0
  • 1、盤面一覽 周二大盤小幅低開后就開始震蕩走弱,失守了10日均線,以消費(釀酒、保險、維生素、家用電器等)和...
    阿凱古閱讀 431評論 0 2
  • 當我們的iOS應用集成了友盟的bug搜集sdk,應用上線后如果出現崩潰,崩潰日志將會被下來,通常我們可以很輕松的得...
    007Mango閱讀 4,001評論 1 1