ggplot2是《The Grammar of Graphics》/《圖形的語法》中提出了一套圖形語法,將圖形元素抽象成可以自由組合的要素,類似Photoshop中的圖層累加,ggplot2將指定的元素/映射關係逐層疊加,最終形成所圖形。更加深入學習ggplot2,請參考《ggplot2: 數據分析與圖形藝術》。
目 錄
引言:ggplot2基本要素
1. 數據(Data)和映射(Mapping)
2、幾何對象(Geometric)
3、標度(Scale):fill、color、shape
4、統計變換(Stat)
5、坐標系統(Coordinante)
6、分面(Facet)
7、主題(Theme)
8、實例:0-1分色
附:ggplot2函數速查表
引言:ggplot2基本要素
「+」和「%+%」
數據(data)和映射(mapping):想要可視化的數據(data)以及一系列將數據中的變量對應到圖形屬性的映射(mapping);ggplot2的數據(data)必須是一個數據框(dataframe)。
幾何對象(geometric):幾何對象(geom)代表你在圖中實際看到的元素,如點、線、多邊形等。
統計變換(statistics):統計變換(stat)是對數據進行的某種匯總。例如將數據分組計數以創建直方圖,或將一個二維的關係用線性模型進行解釋。統計變換是可選的,但通常非常有用。
標度(Scale):標度(scale)的作用是將數據的取值映射到圖形空間,例如用顏色、大小或形狀來表示不同的取值。展現標度的常見做法是繪製圖例和坐標軸——它們實際上是從圖形到數據的一個映射,使你可以從圖形中讀取原始的數據。標度包括位置、顏色、大小、形狀、線型。
坐標系統(Coordinate):坐標系(coord)描述了數據是如何映射到圖形所在的平面的,它同時提供了看圖所需的坐標軸和網格線。我們通常使用的是笛卡爾坐標系,但也可以將其變換為其它類型,如極坐標和地圖投影。
圖層(Layer):圖層的作用是生成在圖像上可以被人感知的圖形。一個圖層由4部分組成:數據和圖形屬性映射;一種統計變換;一種幾何對象;一種位置調整方式。
分面(Facet):分面(facet)描述了如何將數據分解為各個子集,以及如何對子集作圖並聯合進行展示。分面也叫作條件作圖或網格作圖。
其中各要素通過「+」以圖層(layer)的方式來粘合構圖(可以簡單理解為要素/圖層疊加符號);另外在ggplot2中,數據集必須為數據框(data.frame)格式,並且可以通過%+%符號調整已有數據集(ggplot2指導文檔中明確寫出「To override the data, you must use %+%」,也就是覆蓋數據必須通過%+%)。以mpg數據集為例。
library(ggplot2)
#繪製基本ggplot圖base <- ggplot(mpg, aes(displ, hwy)) + geom_point()p1 <- base + geom_smooth() + labs(title="圖1") #如圖1
#用%+%調整映射關係中的數據base <- ggplot(mpg, aes(displ, hwy)) + geom_point()# To override the data, you must use %+% #也即覆蓋原始數據必須通過%+%p2 <- base %+% subset(mpg, fl == "p") + labs(title="圖2") #圖2
#第二種調整數據的方法list# Alternatively, you can add multiple components with a list.# This can be useful to return from a function.p3 <- base + list(subset(mpg, fl == "p"), geom_smooth(), labs(title="圖3")) #圖3
###########一頁多圖########library(grid)grid.newpage() ##新建頁面pushViewport(viewport(layout = grid.layout(2,2))) #將頁面分成2*2矩陣vplayout <- function(x,y){ viewport(layout.pos.row = x, layout.pos.col = y)}
print(p1, vp = vplayout(1,1)) #(1,1)的位置畫圖1print(p2, vp = vplayout(1,2)) #(1,2)的位置畫圖2print(p3, vp = vplayout(2,1)) #(2,1)的位置畫圖31. 數據(Data)和映射(Mapping)
前文已經提及在ggplot2中,數據集必須為數據框(data.frame)格式,並且可以通過%+%符號調整已有數據集。
映射是將一個變量中離散或連續的數據與一個圖形屬性中以不同的參數來相互關聯, 而設定能夠將這個變量中所有的數據統一為一個圖形屬性。aes()函數是ggplot2中的映射函數, 所謂的映射即為數據集中的數據關聯到相應的圖形屬性過程中一種對應關係(注意第10行)。可以發現, 在p2中, 通過aes()指定了橫縱坐標分別為wt和hp
> p1 <- ggplot(data = mtcars)> summary(p1)data: mpg, cyl, disp, hp, drat, wt, qsec, vs, am, gear, carb [32x11]faceting: <ggproto object: Class FacetNull, Facet, gg> ……
> p2 <- ggplot(data = mtcars, mapping = aes(x = wt, y = hp))> summary(p2)data: mpg, cyl, disp, hp, drat, wt, qsec, vs, am, gear, carb [32x11]mapping: x = ~wt, y = ~hpfaceting: <ggproto object: Class FacetNull, Facet, gg> ……另外,在ggplot2中,ggplot()函數聲明了全局數據和映射關係,在後續幾何對象中如未重新設定數據和映射關係,幾何對象將沿用ggplot()中聲明的數據與映射關係;
當然幾何對象可重新設定數據與映射關係,並作用於此幾何對象(對比圖4和圖7),但並不對初始圖圖層產生影響(對比圖4和圖6,圖6雖對幾何圖形中重新定義y變量為carb,但縱坐標依然是wt)。
#library(ggolot2)p <- ggplot(mtcars, aes(x = mpg, y = wt))
p4 <- p + geom_point() + labs(title="圖4")#圖4沿用默認的映射關係來繪製散點圖
p5 <- p + geom_point(aes(shape = factor(carb))) + labs(title="圖5") p6 <- p + geom_point(aes(y = carb)) + labs(title="圖6")#圖6修改默認的y的映射關係, 注意圖中y軸名稱仍然以默認的wt表示
df <- mtcars[which(mtcars$am==1),]p7 <- p + geom_point(data = df,aes(x = mpg, y = wt)) + labs(title="圖7")#重新定義point幾何對象中的數據與映射關係
###########一頁多圖#########library(grid)grid.newpage() pushViewport(viewport(layout = grid.layout(2,2))) vplayout <- function(x,y){ viewport(layout.pos.row = x, layout.pos.col = y)}
print(p4, vp = vplayout(1,1)) print(p5, vp = vplayout(1,2)) print(p6, vp = vplayout(2,1)) print(p7, vp = vplayout(2,2))2、幾何對象(Geometric)
上述例子中,數據映射關係有ggplot()函數設定,使用geom_point()添加一個幾何圖層,告訴ggplot繪畫點圖,並將圖層屬性映射到散點上。
geom_point之外,ggplot2提供了多種幾何對象映射,如geom_histogram直方圖,geom_bar畫柱狀圖,geom_boxplot畫箱式圖等等。不同的幾何對象,要求的屬性會有些不同,這些屬性也可以在幾何對象映射時提供。
> library(ggplot2)> ls("package:ggplot2", pattern="^geom_.+") [1] "geom_abline" "geom_area" "geom_bar" "geom_bin2d" "geom_blank" [6] "geom_boxplot" "geom_col" "geom_contour" "geom_count" "geom_crossbar" [11] "geom_curve" "geom_density" "geom_density_2d" "geom_density2d" "geom_dotplot" [16] "geom_errorbar" "geom_errorbarh" "geom_freqpoly" "geom_hex" "geom_histogram" [21] "geom_hline" "geom_jitter" "geom_label" "geom_line" "geom_linerange" [26] "geom_map" "geom_path" "geom_point" "geom_pointrange" "geom_polygon" [31] "geom_qq" "geom_qq_line" "geom_quantile" "geom_raster" "geom_rect" [36] "geom_ribbon" "geom_rug" "geom_segment" "geom_sf" "geom_sf_label" [41] "geom_sf_text" "geom_smooth" "geom_spoke" "geom_step" "geom_text" [46] "geom_tile" "geom_violin" "geom_vline"#library(ggplot2)p <- ggplot(mtcars, aes(x = mpg, y = wt))p8 <- p + geom_point() + labs(title="圖8")
p <- ggplot(mtcars, aes(x = factor(carb), y = wt))p9 <- p + geom_bar(stat= 'identity') + labs(title="圖9")
###########一頁多圖#########library(grid)grid.newpage() pushViewport(viewport(layout = grid.layout(1,2))) vplayout <- function(x,y){ viewport(layout.pos.row = x, layout.pos.col = y)}
print(p8, vp = vplayout(1,1)) print(p9, vp = vplayout(1,2))3、標度(Scale):fill、color、shape
在對圖形屬性進行映射之後,使用標度可以控制這些屬性的顯示方式,比如顏色屬性、形狀屬性等。
對比圖10和圖11,aes中color參數屬性可以發現,如color對應變量為factor因子時,圖10中圖例分組顯示不同顏色;但如factor對應的變量為數值,ggplot將其識別為連續變量,數值大小決定顏色深度;對比12和圖13,不論是在ggplot函數中定義color還是在幾何對象中定義color,其具有相同的效果。
#library(ggplot2)p <- ggplot(mtcars, aes(x = mpg, y = wt))p10 <- p + geom_point(aes(color=factor(gear))) + labs(title="圖10") p11 <- p + geom_point(aes(color=gear)) + labs(title="圖11")
p <- ggplot(mtcars, aes(x = mpg, y = wt,color = factor(gear)))p12 <- p + geom_point(aes(shape=factor(cyl))) + labs(title="圖12")
p <- ggplot(mtcars, aes(x = mpg, y = wt))p13 <- p + geom_point(aes(color=factor(gear),shape=factor(cyl))) + labs(title="圖13")
###########一頁多圖#########library(grid)grid.newpage() pushViewport(viewport(layout = grid.layout(2,2))) vplayout <- function(x,y){ viewport(layout.pos.row = x, layout.pos.col = y)}
print(p10, vp = vplayout(1,1)) print(p11, vp = vplayout(1,2)) print(p12, vp = vplayout(2,1)) print(p13, vp = vplayout(2,2))4、統計變換(Stat)
統計變換對原始數據進行某種計算,然後在圖上顯示出來,例如在散點圖上加一條回歸線。
ggplot(mtcars, aes(x = mpg, y = wt))+geom_point()+scale_y_log10()+stat_smooth(method = "auto", formula = y ~ x)
aes所提供的參數,就通過ggplot提供,而不是提供給geom_point,因為ggplot裡的參數,相當於全局變量,geom_point()和stat_smooth()都知道x,y的映射,如果只提供給geom_point(),則相當於是局部變量。ggplot2提供了多種統計變換方式:
> library(ggplot2)> ls("package:ggplot2",pattern="stat_.+") [1] "stat_bin" "stat_bin_2d" "stat_bin_hex" "stat_bin2d" "stat_binhex" [6] "stat_boxplot" "stat_contour" "stat_count" "stat_density" "stat_density_2d" [11] "stat_density2d" "stat_ecdf" "stat_ellipse" "stat_function" "stat_identity" [16] "stat_qq" "stat_qq_line" "stat_quantile" "stat_sf" "stat_sf_coordinates" [21] "stat_smooth" "stat_spoke" "stat_sum" "stat_summary" "stat_summary_2d" [26] "stat_summary_bin" "stat_summary_hex" "stat_summary2d" "stat_unique" "stat_ydensity" [31] "update_stat_defaults"5、坐標系統(Coordinante)
坐標系統控制坐標軸進行變換,例如XY軸翻轉,笛卡爾坐標和極坐標轉換。
#設置基本映射關係p <- ggplot(mtcars)p14 <- p + geom_bar(aes(x = factor(carb)))+coord_flip() + labs(title="圖14")
#坐標軸翻轉由coord_flip()實現p15 <- p + geom_bar(aes(x = factor(carb)))+coord_flip() + labs(title="圖15")
#轉換成極坐標可以由coord_polar()實現:風玫瑰圖(windrose)p16 <- p + geom_bar(aes(x = factor(1),fill=factor(gear))) + coord_polar() + labs(title="圖16")
#轉換成極坐標可以由coord_polar()實現:風玫瑰圖(windrose)p17 <- p + geom_bar(aes(x = factor(carb),fill=factor(gear))) + coord_polar() + labs(title="圖17")
###########一頁多圖#########library(grid)grid.newpage() pushViewport(viewport(layout = grid.layout(2,2))) vplayout <- function(x,y){ viewport(layout.pos.row = x, layout.pos.col = y)}
print(p14, vp = vplayout(1,1)) print(p15, vp = vplayout(1,2)) print(p16, vp = vplayout(2,1)) print(p17, vp = vplayout(2,2))6、分面(Facet)
分面可以讓我們按照某種給定的條件,對數據進行分組,然後分別畫圖。
#facet_gridmt <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) + geom_point()mt + facet_grid(. ~ cyl, scales = "free")#facet_wrapggplot(mpg, aes(displ, hwy)) + geom_point() + facet_wrap(~class, scales = "free")7、主題(Theme)
p1 <- ggplot(mtcars, aes(wt, mpg)) + geom_point() + labs(title = "Fuel economy declines as weight increases") + labs(title="圖20") p17 <- p1 + theme(plot.title = element_text(size = rel(2))) + labs(title="圖17") p18 <- p1 + theme(plot.background = element_rect(fill = "green")) + labs(title="圖18") p19 <- p1 + theme(panel.background = element_rect(fill = "white", colour = "grey50")) + labs(title="圖19")
###########一頁多圖#########library(grid)grid.newpage() pushViewport(viewport(layout = grid.layout(2,2))) vplayout <- function(x,y){ viewport(layout.pos.row = x, layout.pos.col = y)}
print(p1, vp = vplayout(1,1)) print(p17, vp = vplayout(1,2)) print(p18, vp = vplayout(2,1)) print(p19, vp = vplayout(2,2))8 實例
set.seed(1)x <- 1980 + 1:50y <- round(100*rnorm(50))df <- data.frame(x = x,y = y)# 判斷y是否為正值df <- transform(df,judge = ifelse(y>0,"YES","NO"))# 去除圖例用theme()主題函數ggplot(df,aes(x = x,y = y,fill = judge))+geom_bar(stat = "identity")+theme(legend.position= "")+xlab("Year")+scale_fill_manual(values = c("darkred","blue"))【ggplot2函數速查表】
地址:https://ggplot2.tidyverse.org/
—————————————
往期精彩: