一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

R統(tǒng)計繪圖(1): ggplot2入門指南

 小夢想在努力 2018-12-29

前言

ggplot2是R語言最流行的第三方擴展包,是RStudio首席科學(xué)家Hadley Wickham讀博期間的作品,是R相比其他語言一個獨領(lǐng)風(fēng)騷的特點。包名中“gg”是grammar of graphics的簡稱,是一套優(yōu)雅的繪圖語法。Wickham Hadley將這套語法詮釋如下:

一張統(tǒng)計圖形就是從數(shù)據(jù)幾何對象(geometric object,縮寫geom)的圖形屬性(aesthetic attribute,縮寫aes)的一個映射。此外,圖形中還可能包含數(shù)據(jù)的統(tǒng)計變換(statistical transformation,縮寫stats),最后繪制在某個特定的坐標系(coordinate system,縮寫coord)中,而分面(facet)則可以用來生成數(shù)據(jù)不同子集的圖形。

這個解釋讀起來還是有點抽象。我們舉個具體的例子來解讀這個概念。假設(shè)現(xiàn)在我們要對一批連續(xù)取值的數(shù)據(jù)繪制直方圖。首先,要定義清楚需要幾個分組或者每個分組的區(qū)間,根據(jù)分組定義統(tǒng)計落在這個分組里的個數(shù),這個步驟就是把data變?yōu)?strong>stats。然后,需要選定表達數(shù)據(jù)的幾何對象,這個例子選用的是條塊bar,這個步驟就是選geomgeom有一堆屬性需要設(shè)定,比如x、y、顏色等,稱為aes,哪個aes由哪個stats指定,需要指定一個映射關(guān)系mapping,即指定誰對誰。知道誰對誰后,還需要知道怎么個對法,需要由scale決定,比如stats的color字段取值為1應(yīng)該對到什么顏色上,取值為2應(yīng)該對到什么顏色上。這些完成了以后,統(tǒng)計圖形的主體部分就成形了,但是假如我們希望在直方圖上,再畫一個概率密度曲線圖,怎么辦?ggplot2的思想非常精妙,把上面的主體部分稱為一個圖層layer,一個統(tǒng)計圖形可以擁有多個圖層,每個圖層疊加起來形成我們要的效果。接下來,再選定一個坐標系統(tǒng)coord,一張統(tǒng)計圖形plot就做好了。假如我們有多組數(shù)據(jù),每組數(shù)據(jù)都要按照相同的方法畫一張圖,每張圖重復(fù)敲代碼很繁瑣,就可以使用分面facet快速繪制多張統(tǒng)計圖形。這個過程用圖形總結(jié)如下:

clipboard.png

我們可以看到ggplot2相比其他繪圖系統(tǒng)的幾個特性:

  • 標準化:任何一個統(tǒng)計圖形遵循相同的繪圖流程,所以語法高度統(tǒng)一;

  • 面向數(shù)據(jù):上面的繪圖流程只與數(shù)據(jù)有關(guān),與數(shù)據(jù)無關(guān)的繪圖細節(jié)封裝在單獨的theme()方法里,數(shù)據(jù)相關(guān)繪圖與數(shù)據(jù)無關(guān)繪圖分離;

這兩大特性解放了數(shù)據(jù)分析師的思維,做到繪圖時所思即所見,非常優(yōu)雅高效。下面我們來逐步剖析每個元素的內(nèi)容。

數(shù)據(jù)

ggplot2接受的輸入數(shù)據(jù)一般是data.frame,這是一個表格型結(jié)構(gòu),每一行是一個觀測(observation),每一列是一個變量(variable)。R語言內(nèi)置了許多著名的數(shù)據(jù)集,本文選取其中的iris進行講解。iris中文名是鳶尾花,有四個屬性,分別是Sepal.Length(花萼長度),Sepal.Width(花萼寬度),Petal.Length(花瓣長度),Petal.Width(花瓣寬度),以及一個類別標簽Species。我在網(wǎng)上找了一個圖片,做個標注,方便朋友理解。

clipboard.png

我們可以使用str()查看數(shù)據(jù)集的結(jié)構(gòu),用summary()對每一個變量進行統(tǒng)計。

str(iris)

clipboard.png

summary(iris)

clipboard.png

Hadley對data.frame提出了一個是否tidy的概念,抽象來講就是一個變量必須有自己獨立的一列,一個觀測必須有自己獨立的一行,每個取值必須有自己獨立的一個單元格。為了便于理解,我們從R for Data Science這本書截取出這個圖進行解釋:

clipboard.png

左邊的數(shù)據(jù)是tidy的,右邊的數(shù)據(jù)是不tidy的,通過另一個包tidyr可以輕松完成二者的轉(zhuǎn)換。ggplot2的數(shù)據(jù)要求是tidy的。

統(tǒng)計圖形基本要素

幾何對象geom

幾何對象,說的直觀一些,就是你選擇什么幾何圖形來表示這組數(shù)據(jù)。ggplot2提供了眾多幾何對象geom_xyz()供大家選擇。舉兩個常見的例子,geom_point()用于表示兩個連續(xù)變量之間的關(guān)系,幾何形狀是點;geom_bar()用于表示x軸為離散變量,y軸為連續(xù)連續(xù)變量之間的關(guān)系,幾何形狀是條塊。完整的幾何對象請下載RStudio公司總結(jié)的ggplot2 cheetsheet。

幾何對象需要解決一個問題,即相同數(shù)據(jù)的幾何對象位置相同,是放在一個位置相互覆蓋還是用別的排列方式。ggplot2的幾何對象有一個position選項,用于指定如何在空間內(nèi)布置相同取值的集合對象。dodge為并排模式;fill為堆疊模式,并歸一化為相同的高度;stack為純粹的堆疊模式;jitter會在X和Y兩個方向增加隨機的擾動來防止對象之間的覆蓋。

統(tǒng)計變換stats

在ggplot2里,幾何對象與統(tǒng)計變換往往是一一對應(yīng)的。每個統(tǒng)計變換需要通過一個幾何對象來展現(xiàn);每個幾何對象的展現(xiàn)依賴統(tǒng)計變換的結(jié)果。舉個簡單例子,以下兩行代碼的效果是一樣的:

ggplot(iris) + geom_bar(aes(x=Sepal.Length), stat="bin", binwidth = 3)
ggplot(iris) + stat_bin(aes(x=Sepal.Length), geom="bar", binwidth = 3)

圖形屬性aes

每個幾何對象都有自己的屬性,這些屬性的取值需要通過數(shù)據(jù)提供。數(shù)據(jù)與圖形屬性之間的映射關(guān)系稱為mapping,在ggplot2中用aes()進行定義。常見的圖形屬性有:x,y,sizecolor,group。圖形屬性的任意一項都可以用數(shù)據(jù)的某一個變量來表示。

標尺scale

前面提到aes()設(shè)定了數(shù)據(jù)與圖形屬性的映射關(guān)系,但是數(shù)據(jù)怎么映射為屬性,這就是標尺(Scales)的功能。對于任何一個圖形屬性,如x,y,alpha,color,fill,linetypeshape,size,ggplot2都提供以下四種標尺:

  • scale_*_continuous():將數(shù)據(jù)的連續(xù)取值映射為圖形屬性的取值

  • scale_*_discrete():將數(shù)據(jù)的離散取值映射為圖形屬性的取值

  • scale_*_identity():使用數(shù)據(jù)的值作為圖形屬性的取值

  • scale_*_mannual():將數(shù)據(jù)的離散取值作為手工指定的圖形屬性的取值

舉個例子

group_iris <- iris %>% group_by(Species) %>% dplyr::summarise(avg_sepal_length=mean(Sepal.Length))
str(group_iris)
p <- ggplot(group_iris) + geom_bar(aes(x=Species, weight=avg_sepal_length, fill=Species))
p

clipboard.png

p + scale_fill_manual(
  values = c("skyblue", "royalblue", "navy"), # mannual類scale特有的選項,指定圖形屬性的取值范圍
  limits = c("setosa", "versicolor", "virginica"), # 數(shù)據(jù)的取值范圍
  breaks = c("setosa", "versicolor", "virginica"), # 圖例和軸要顯示的分段點
  name = "Species",  # 圖例和軸使用的名稱
  labels = c("set", "ver", "vir")  # 圖例使用的標簽
)

clipboard.png

除了上述四大類通用的標尺,特定的圖形屬性還有一些專門的標尺類型。對于xy類圖形屬性,有如下幾種特殊的標尺:

  • scale_x_date(labels=date_format("%m/%d"), breaks=date_breaks("2 weeks"))

  • scale_x_datetime()

  • scale_x_log10()

  • scale_x_reverse()

  • scale_x_sqrt()

對于colorfill類的圖形屬性,有如下幾類特殊標尺:

  • scale_fill_brewer(palette="Blues"):根據(jù)調(diào)色盤生成顏色標尺,可用的調(diào)色盤可以通過RColorBrewer::display.brewer.all()命令查看;對于具體的一個調(diào)色盤,可以通過RColorBrewer::brewer.pal(n=4, name="Blues")查看具體某個名字調(diào)色盤的n個配色值。

  • `scale_fill_grey(start=0.2, end=0.8, na.value="red"):灰度標尺

  • scale_fill_gradient(low="red", high="yellow"):雙色漸變標尺

  • scale_fill_gradient2(low="red", high="blue", mid="white", midpoint=25):三色漸變標尺

  • scale_fill_gradientn(colours=terrain.colors(6)):n色漸標尺,其他的調(diào)色盤有rainbow()heat.colors(),topo.colors()cm.colors()以及RColorBrewer包的調(diào)色盤。

對于shape類的圖形屬性,我們可以手工指定形狀:scale_shape_manual(values=c(3:7)。每個形狀用數(shù)字表示,根據(jù)下圖可以選擇自己需要的形狀。

clipboard.png

圖層layer

ggplot2的繪圖過程有點像Photoshop,有一個圖層的理念,每個圖層可以有自己的圖形對象和圖形屬性,通過+將不同圖層疊加起來生成最后的統(tǒng)計圖形。如果將數(shù)據(jù)定義在ggplot()中,那么所有圖層都可以共用這個數(shù)據(jù);如果將數(shù)據(jù)定義在geom_xyz()中,那么這個數(shù)據(jù)就只供這個幾何對象使用。

坐標系coord

ggplot2默認的坐標系是笛卡爾坐標系,可以用如下方法指定取值范圍:coord_cartesian(xlim=c(0,5), ylim=c(0,3))。如果想要讓x軸和y軸換位置,比如將柱形圖換成條形圖,可以使用coord_flip()函數(shù)。coord_polar(theta="x", direction=1)是角度坐標系,theta指定角度對應(yīng)的變量,start指定起點離12點鐘方向的偏離值,direction若為1表示順時針方向,若為-1表示逆時針方向。

掌握了數(shù)據(jù)、幾何對象、圖形屬性、圖層和坐標系的概念后,我們就可以開始繪制常見的統(tǒng)計圖形了。

練習(xí)

Kaggle數(shù)據(jù)挖掘競賽里有一個經(jīng)典的探索性分析例子,對iris數(shù)據(jù)集進行了各種形式的可視化,幫助人通過直觀的圖形更深地理解特征與label的關(guān)系。Kaggle官網(wǎng)給出了Python版本的實現(xiàn)。本節(jié)用R對該notebook的代碼進行重現(xiàn)。

library(ggplot2)

# Make scatter plot of Sepal.Length and Sepal.Width
p.scatter <- ggplot(iris) + geom_point(aes(x=Sepal.Length, y=Sepal.Width))
p.scatter

clipboard.png

# One piece of information missing in the plots above is what species each plant is
p.scatter <- ggplot(iris) + geom_point(aes(x=Sepal.Length, y=Sepal.Width, color=Species))
p.scatter

clipboard.png

# Boxplot to explore numeric variable
p.box <- ggplot(iris) + geom_boxplot(aes(x=Species, y=Petal.Length))
p.box

clipboard.png

# One way we can extend this plot is adding a layer of individual points on top of it
p.box.jitter <- p.box + geom_jitter(aes(x=Species, y=Petal.Length))
p.box.jitter

clipboard.png

# A violin plot combines the benefits of the previous two plots and simplifies them
# Denser regions of the data are fatter, and sparser thiner in a violin plot
p.violin <- ggplot(iris) + geom_violin(aes(x=Species, y=Petal.Length))
p.violin

clipboard.png

# A final plot useful for looking at univariate relations is the kdeplot,
p.density <- ggplot(iris) + geom_density(aes(x=Petal.Length, colour=Species)) 
p.density

clipboard.png

分面

分面,就是分組繪圖,根據(jù)定義的規(guī)則,將數(shù)據(jù)分為多個子集,每個子集按照統(tǒng)一的規(guī)則單獨制圖,排布在一個頁面上。ggplot2提供兩種分面模式:facet_grid()facet_wrap()。

我們先來看一下facet_grid()的效果。

library(tidyr)
library(dplyr)
# 將數(shù)據(jù)變?yōu)閠idy的
tidy_iris <- iris %>% 
  gather(feature_name, feature_value, one_of(c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")))

p.box.facet <- ggplot(tidy_iris) + geom_boxplot(aes(x=Species, y=feature_value)) + facet_grid(feature_name~Species)
p.box.facet

clipboard.png

可以看到facet_grid()是一個二維的矩形布局,每個子集的位置由行位置變量~列位置變量的決定,在上面的例子中就是每一個Species的取值作為一行,每一個feature_name的取值作為一列。

再來看一下facet_wrap()的效果。

p.box.facet <- ggplot(tidy_iris) + geom_boxplot(aes(x=Species, y=feature_value)) + facet_wrap(~feature_name+Species, scales="free")
p.box.facet

clipboard.png

facet_wrap()生成一個動態(tài)調(diào)整的一維布局,根據(jù)~位置變量1+位置變量2+...來確定每個子集的位置,先逐行排列,放不下了移動到下一行。scales="free"讓每個子圖的坐標系適合自己的數(shù)據(jù),便于在有限的空間里充分展示子圖的細節(jié),但也失去了不同子圖之間比較的作用,需要謹慎使用。

題外話:復(fù)雜布局

分面的特點是可以快速生成多個子圖,每個子圖的生成方式是一樣的,因此只需要指定分組的規(guī)則即可。但是有時候我們希望繪制多個子圖,每個子圖的生成方法卻不一樣,這個時候分面就不起作用了,需要使用grid包提供的布局功能。下面我們用ggplot2和grid的布局實現(xiàn)一個較為復(fù)雜的統(tǒng)計圖形效果:

library(grid)
# Show bivariate scatter plot and univariate histogram
p.hist.len <- ggplot(iris) + geom_histogram(aes(x=Sepal.Length))
p.hist.wid <- ggplot(iris) + geom_histogram(aes(x=Sepal.Width)) + coord_flip()
grid.newpage()
pushViewport(viewport(layout = grid.layout(3, 3)))
print(p.scatter, vp=viewport(layout.pos.row=2:3, layout.pos.col=1:2))
print(p.hist.len, vp=viewport(layout.pos.row=1, layout.pos.col=1:2))
print(p.hist.wid, vp=viewport(layout.pos.row=2:3, layout.pos.col=3))

clipboard.png

在做數(shù)據(jù)分析時,我們經(jīng)常需要觀察變量自身與變量之間的兩兩關(guān)系。這個過程中需要繪制大量的圖表,且每個業(yè)務(wù)的數(shù)據(jù)分析都需要這么做,因此算是一種重復(fù)性比較大的工作。我們可以使用GGally包來快速完成這個探索性分析的任務(wù)。

library(GGally)
# Another useful seaborn plot is the pairplot, which shows the bivariate relation
# between each pair of features
# 
# From the pairplot, we'll see that the Iris-setosa species is separataed from the other
# two across all feature combinations

ggpairs(iris, aes(colour=Species), alpha=0.4) # R could be better!!

clipboard.png

題外話:其他練習(xí)

Kaggle數(shù)據(jù)挖掘競賽剩下的例子是繪制Parallel coordinate graph、Andrews Curve、radviz,前兩個的實現(xiàn)參考如下,最后一個暫時沒找到對應(yīng)的方法。

# Parallel coordinate graph & Andrews Curve
# 修改自:http:///2009/03/parallel-coordinates-and-andrews-curve/
# 輪廓圖的思想非常簡單、直觀,它是在橫坐標上取n個點,依次表示各個指標(即變量);橫坐標上則對應(yīng)各個指標的值(或者經(jīng)過標準化變換后的值),然后將每一組數(shù)據(jù)對應(yīng)的點依次連接即可
# 調(diào)和曲線圖的思想和傅立葉變換十分相似:
# 根據(jù)三角變換方法將 n 維空間的點映射到二維平面上的曲線上,其中x取值范圍為[-pi,pi]。

# Another multivariate visualization technique pandas has is parallel_coordinates
# Parallel coordinates plots each feature on a separate column & then draws lines
# connecting the features for each data sample

p.paral <- ggplot(cbind(iris %>% gather(feature_name, feature_value, one_of(c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"))), id=1:nrow(iris))) + geom_line(aes(x=feature_name, y=feature_value, group=id, colour=Species))
p.paral

clipboard.png

# One cool more sophisticated technique pandas has available is called Andrews Curves
# Andrews Curves involve using attributes of samples as coefficients for Fourier series
# and then plotting these
andrews_curve <- function(data, x_col, y_col, step=pi/30){
  x = as.matrix(data[, x_col])
  t = seq(-pi, pi, pi/30)
  m = nrow(x)
  n = ncol(x)
  f = matrix(0, m, length(t))
  for(i in 1:m) {
    f[i,] = x[i,1]/sqrt(2)
    for(j in 2:n) {
      if (j%%2 == 0)
        f[i, ] = f[i, ] + x[i, j] * sin(j/2 * t)
      else f[i, ] = f[i, ] + x[i, j] * cos(j%/%2 * t)
    }
  }
  colnames(f) <- t
  label <- data[, y_col]
  id <- c(1:nrow(f))
  res <- cbind(as.data.frame(f), label, id)  %>%
    gather(x, y, -label, -id, convert = TRUE)
}

iris.andrew <- andrews_curve(iris, x_col=c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"), y_col="Species")
p.andrew <- ggplot(iris.andrew) + geom_line(aes(x, y, group=id, color=label))
p.andrew

clipboard.png

# A final multivariate visualization technique pandas has is radviz
# Which puts each feature as a point on a 2D plane, and then simulates
# having each sample attached to those points through a spring weighted
# by the relative value for that feature

# 暫時沒能力實現(xiàn)

其他元素

主題

所有與數(shù)據(jù)不相關(guān)的圖形控制細節(jié)都放在theme()這個函數(shù)里。ggplot2內(nèi)置了一些常見的主題:theme_bw(),theme_classic(),theme_grey()theme_minimal()。如果需要更多的主題可以安裝ggthemes包,也可以自定義主題。

圖例

ggplot2可以設(shè)定圖例的位置:theme(legend.position="bottom"),其他選項有top、left和right。

每個圖形屬性都會有一個圖例,圖例的類型共有三種:colorbar為顏色條,適合連續(xù)變量;legend為鍵值對,適合有限取值的變量;none,將一個圖形屬性的圖例設(shè)置為none,則不顯示這個圖形屬性的圖例。

標簽

常用的繪圖標簽有:

  • ggtitle("New Plot Title"):指定圖形名稱

  • xlab("New X label"):指定x軸標簽

  • ylab("New Y label"):指定y軸標簽

  • 圖例標簽需要使用scale_*()namelabels選項進行指定

關(guān)于作者:丹追兵,數(shù)據(jù)分析師一枚,編程語言python和R,使用Spark、Hadoop、Storm、ODPS。本文出自丹追兵的pytrafficR專欄,轉(zhuǎn)載請注明作者與出處:https://segmentfault.com/blog...

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    我想看亚洲一级黄色录像| 国产男女激情在线视频| 麻豆国产精品一区二区| 大香蕉伊人精品在线观看| 久久午夜福利精品日韩| 国产老熟女乱子人伦视频| 国产午夜福利一区二区| 国产一区欧美一区日本道| 亚洲性生活一区二区三区| 国产毛片不卡视频在线| 国产乱久久亚洲国产精品| 少妇特黄av一区二区三区| 成人日韩视频中文字幕| 久久成人国产欧美精品一区二区 | 天海翼精品久久中文字幕| 国产精品一区二区三区日韩av | 国产又粗又长又爽又猛的视频| 视频一区二区黄色线观看| 国产又色又爽又黄的精品视频| 国产性色精品福利在线观看| 亚洲欧洲精品一区二区三区| 日韩欧美高清国内精品| 欧美日韩综合综合久久久| 黑人粗大一区二区三区| 99亚洲综合精品成人网色播| 在线视频三区日本精品| 亚洲欧美日韩国产综合在线| 国产精品福利一二三区| 国产一级精品色特级色国产| 国产真人无遮挡免费视频一区| 欧美日韩综合综合久久久| 蜜臀人妻一区二区三区| 日本人妻的诱惑在线观看| 日本午夜免费观看视频| 邻居人妻人公侵犯人妻视频| 午夜国产精品福利在线观看| 国产一级内片内射免费看 | 国产亚洲欧美另类久久久| 国产一级二级三级观看| 亚洲av又爽又色又色| 亚洲国产成人精品一区刚刚|