前言
ggplot2是數據可視化的重要程序包,用於繪製各種高級統計圖形。該程序包是紐西蘭統計學家Hadley Wickham在2005年左右開發的,那時候作者還是美國Iowa大學的博士生。
ggplot2的命令是一種用R實現的繪圖語言ggplot2的代碼相對容易理解,設定各種參數較為方便,圖形也十分美觀,能用相對簡單的代碼在圖形中呈現出非常豐富的信息。不過,ggplot2的語法與傳統R函數的調用方式有很大差別,所以不少人反映學起來有些困難。
在ggplot2出現以前,R繪圖都是調用函數,再通過改變函數的參數實現的。ggplot2將所繪製圖形的各部分獨立出來,如xy坐標,基本組件的顏色、圖標大小、填充類型、堆疊方式、坐標軸、地圖投影、數據分組、圖形分面等等信息劃歸為一些基本類型,每一部分分別用一段代碼表示。每段代碼內部有相應的參數控制,各代碼段再通過「+」運算符連接。這裡的「+」並非四則運算的加法,而是表示圖形各要素/組件之間的疊加。「+」運算符所連接的代碼片段,有任何一部分做出更改,整個圖形就做出相應調整。因此,本質上,ggplot2代碼是用R語言實現的一種繪圖語言。
ggplot2所用的繪圖語言,主要是按照Wilkinson(2005)的設想實現的。Wilkinson(2005)將一幅統計圖形看做由以下幾個主要部分:
數據;
表現數據的點、線、多邊形、柵格、顏色等;
坐標系
ggplot2命令的基本組成具體來講,在ggplot2程序包中,每一副圖都是由若干組件組成的,這些組件包括:
data: 數據,必須為data.frame。
coordinate system: 數據可視化,主要是在二維平面上表示數據的關係,所用坐標系一般為平面直角坐標,有時會用到極坐標、地圖投影等。ggplot2軟體默認使用平面直角坐標。
geoms: 包括geoms_開頭的各種對象,用來繪製各種基本組件,包括點、線、面、多邊形、柱狀圖、箱線圖等。
aesthetics: 圖形的美學特徵,如顏色、形狀、透明度、大小、分組等。
scales: 坐標軸的屬性
stats: 統計變換。用於設定數據要進行的統計轉換,例如平均值、中位數、記錄數等。
facets: 描述如何將圖形按照某一個或者幾個因子(factors)不同水平(levels)用多個圖形分開展示。
ggplot2要求輸入數據為data.frameggplot2要求輸入的數據為data.frame。為了將R中的各種數據轉換為ggplot2能夠讀取和操作的data.frame格式,H. Wickham還開發了reshape2以及dplyr等程序包,專門用於數據轉換。
ggplot2中的aes函數完整的ggplot2繪圖命令, 總是以ggplot() 開始。ggplot()及其參數奠定整個ggplot2圖形的基礎,最重要的兩個參數為data和mapping。其中data必須為data.frame格式。mapping參數要求數據通過aes函數進一步轉換。aes是aesthetic的縮寫。在aes函數中,要輸入的參數有x, y, group, color, size等。aes可以直接訪問data參數所輸入數據框的各列,從而直接控制圖形的橫坐標、縱坐標、分組以及各組的顏色、大小、透明度等等。
注意:在ggplot()代碼部分設置的aes參數對於整個圖形都有效。在某個geom組件內部設置的aes參數,如顏色、分組、字體大小、線段類型等,只對該geom組件有效。若要設定所有geom組件的形狀、大小、顏色等,相應的參數如size, color等,不要放入aes函數轉換,而是作為ggplot()函數的普通參數即可。
ggplot2的geom組件ggplot()代碼段只定義數據展示的邏輯關係,並不直接繪圖。要用ggplot2繪圖,還必須為其添加各種基本圖形組件。要添加的圖形組件根據變量的數目以及要繪製的圖形有所不同,包括:點geom_point、線geom_line、多邊形geom_polygon、箱線圖geom_boxplot、柱狀圖geom_bar、六角形圖geom_hex、柵格圖geom_tile、階梯線geom_step、擬合的趨勢線geom_smooth等等。
為了對圖形進行進一步修飾,還可能要更改圖形的橫坐標、縱坐標、標題等等。
ggplot2圖形的顯示ggplot2所生成的對象,同時具有gg和ggplot兩種屬性。如果要顯示圖形,需要將其print到屏幕上,而不是像plot()函數一樣直接調用函數就可以調用繪圖設備(屏幕也是繪圖設備)。與此同時,ggplot2的圖形也不接受par()設定的各種參數。
本文就ggplot2的常用繪圖組件做簡要介紹。
快速繪圖 qplot (不建議使用)為了讓只熟悉R基礎繪圖的用戶也能使用ggplot2,H. Wickham編寫了qplot函數,調用方式類似plot()。在qplot()中,所有控制圖形的信息都封裝為參數。但是qplot()在一定程度上降低了繪圖的靈活性,難以體現ggplot2的優勢,因此不太建議使用。
library(maps)
library(ggthemes)
library(ggplot2)
plot(hwy ~ cty, data = mpg)
qplot繪圖qplot(x = cty, y = hwy, color = cyl, data = mpg, geom = "point")
ggplot2繪圖ggplot(data = mpg, aes(x = cty, y = hwy)) +
geom_point(aes(color = cyl)) +
geom_smooth(method = "lm") +
coord_cartesian() +
scale_color_gradient() +
theme_base() +
scale_shape(solid = FALSE) +
ggtitle("New Plot Title") +
xlab("New X label") +
ylab("New Y label")
thismap = map_data("world")
c <- ggplot(thismap, aes(long, lat, group=group))
c + geom_polygon(fill="white", colour="gray")
ggplot(economics, aes(date, unemploy)) +
geom_path(lineend = "butt", linejoin = "round", linemitre = 1)
ggplot(economics, aes(date, unemploy)) +
geom_ribbon(aes(ymin = unemploy - 900, ymax = unemploy + 900))
ggplot(seals, aes(x = long, y = lat)) +
geom_segment(aes(xend = long + delta_long, yend = lat + delta_lat))
ggplot(seals, aes(x = long, y = lat)) +
geom_rect(aes(xmin = long, ymin = lat, xmax = long + delta_long, ymax = lat + delta_lat))
a <- ggplot(mpg, aes(hwy))
頻度陰影圖a + geom_area(stat = "bin")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
核密度圖a + geom_density(kernel = "gaussian")
點狀頻度圖a + geom_dotplot()
## `stat_bindot()` using `bins = 30`. Pick better value with `binwidth`.
頻度折線圖a + geom_freqpoly()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
單變量離散數據b <- ggplot(mpg, aes(fl))
b + geom_bar()
f <- ggplot(mpg, aes(cty, hwy))
f + geom_blank()
f + geom_jitter()
散點圖f + geom_point()
分位數回歸線f + geom_quantile()
## Loading required package: SparseM
##
## Attaching package: 'SparseM'
## The following object is masked from 'package:base':
##
## backsolve
## Smoothing formula not specified. Using: y ~ x
xy軸投影f + geom_rug(sides = "bl")
線性模型擬合以及置信區間f + geom_smooth(method = "lm")
Loess擬合趨勢線以及置信區間f + geom_smooth(method = "auto")
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
x為離散變量,y為連續變量 柱狀圖g <- ggplot(mpg, aes(class, hwy))
g + geom_bar(stat = "identity")
g + geom_boxplot()
點圖g + geom_dotplot(binaxis = "y", stackdir = "center")
## `stat_bindot()` using `bins = 30`. Pick better value with `binwidth`.
小提琴圖g + geom_violin(scale = "area")
x為離散變量, y為離散變量h <- ggplot(diamonds, aes(cut, color))
h + geom_jitter()
data(iris)
i <- ggplot(iris, aes(Sepal.Length, Sepal.Width))
i + geom_bin2d(binwidth = c(5, 0.5))
i + geom_density2d()
六角形密度圖i + geom_hex()
x軸為時間序列的連續變量 陰影圖j <- ggplot(economics, aes(date, unemploy))
j + geom_area()
j + geom_line()
階梯圖j + geom_step(direction = "hv")
添加誤差線df <- data.frame(grp = c("A", "B"), fit = 4:5, se = 1:2)
k <- ggplot(df, aes(grp, fit, ymin = fit-se, ymax = fit+se))
k + geom_crossbar(fatten = 2)
誤差線圖(帶橫線)k + geom_errorbar()
誤差線圖(不帶橫線)k + geom_linerange()
帶誤差線的點圖k + geom_pointrange()
三維數據的可視化seals$z <- with(seals, sqrt(delta_long^2 + delta_lat^2))
m <- ggplot(seals, aes(long, lat))
m + geom_contour(aes(z = z))
柵格圖m + geom_raster(aes(fill = z), hjust=0.5, vjust=0.5, interpolate=FALSE)
瓦片圖m + geom_tile(aes(fill = z))
統計變換a + geom_bar(stat = "bin")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
說明:stat_bin(geom = "bar") 和 geom_bar(stat = "bin") 兩者等價
一維概率密度統計變換參數的設定a + stat_bin(binwidth = 1, boundary = 10)
a + stat_density(adjust = 1, kernel = "gaussian")
二維概率密度統計變換參數的設定f + stat_bin2d(bins = 30, drop = TRUE)
f + stat_binhex(bins = 30)
f + stat_density2d(contour = TRUE, n = 100)
三維數據的統計變換參數設定 等高線圖m + stat_contour(aes(z = z))
線段圖m+ geom_spoke(aes(radius= z, angle = z))
六角形圖m + stat_summary_hex(aes(z = z), bins = 30, fun = mean)
柵格圖m + stat_summary_2d(aes(z = z), bins = 30, fun = mean)
組間比較 箱線圖g + stat_boxplot(coef = 1.5)
提琴圖參數設定g + stat_ydensity(adjust = 1, kernel = "gaussian", scale = "area")
累積曲線f + stat_ecdf(n = 40)
分位數曲線圖f + geom_quantile(quantiles = c(0.25, 0.5, 0.75), formula = y ~ log(x), method = "rq")
Loess回歸以及置信區間統計變換的參數設定f + geom_smooth(method = "auto", formula = y ~ x, se = TRUE, n = 80, fullrange = FALSE, level = 0.95)
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
繪製dnorm的概率密度分布ggplot() + stat_function(aes(x = -3:3), fun = dnorm, n = 101, args = list(sd=0.5))
繪製散點圖f + stat_identity()
繪製qq圖ggplot() + stat_qq(aes(sample=1:100), distribution = qt, dparams = list(df=5))
繪製散點圖, 點的大小為該點數據出現的次數f + stat_sum()
帶誤差線的點圖f + stat_summary(fun.data = "mean_cl_boot")
## Warning: Removed 3 rows containing missing values (geom_pointrange).
無重複散點圖f + stat_unique()
圖例ggplot2 的圖例與圖形是一個整體, 設定圖例的參數, 圖例會更改, 設定圖形的參數, 圖例會自動更改。scale 控制圖形中的顏色,文字顯示, 圖例中的圖形。
n <- b + geom_bar(aes(fill = fl))
n
n + scale_fill_manual(
values = c("skyblue", "royalblue", "blue", "navy"),
limits = c("d", "e", "p", "r"),
breaks =c("d", "e", "p", "r"),
name = "fuel", labels = c("D", "E", "P", "R"))
按照數據的類別, 分為
scale_x_continuous()
scale_x_discrete()
scale_x_identity()
scale_x_manual(values = c())
scale_y_continuous()
scale_y_discrete()
scale_y_identity()
scale_y_manual(values = c())
這幾個函數的參數主要為:
alpha, 透明度
color, 顏色序列
fill, 顏色序列
linetype, 線段類型
shape, 點的形狀
size, 點的大小
x軸顯示日期library(scales)
scale_x_date(labels = date_format("%m/%d"), breaks = date_breaks("2 weeks"))
scale_x_datetime()
x軸轉換為以10為底的對數scale_x_log10()
x軸逆向顯示scale_x_reverse()
x軸平方根變換scale_x_sqrt()
顏色顏色主要用來顯示分組,或者數據的連續梯度變化。
顏色設定在ggplot2中,可以通過scale_fill_brewer(palette = "")函數,可以將色系調整為以下任何一種。
最大差異色系 DivergingBrBG, PiYG, PRGn, PuOr, RdBu, RdGy, RdYlBu, RdYlGn, Spectral
離散色系 QualitativeAccent, Dark2, Paired, Pastel1, Pastel2, Set1, Set2, Set3
序列色系 SequentialBlues, BuGn, BuPu, GnBu, Greens, Greys, Oranges, OrRd, PuBu, PuBuGn, PuRd, Purples, RdPu, Reds, YlGn, YlGnBu, YlOrBr, YlOrRd
通過aes設定分組之後,如fill, color, group等,ggplot會自動設定顏色。點圖、柵格圖等連續變量,默認為深藍色色系(「Diamond\nclarity」)。
調整圖形顏色的函數還包括:
scale_colour_brewer
scale_fill_brewer
scale_colour_distiller
scale_fill_distiller
scale_colour_gradient
scale_fill_gradient
scale_colour_gradient2
scale_fill_gradient2
scale_colour_gradientn
scale_fill_gradientn
scale_colour_grey
scale_fill_grey
scale_colour_hue
scale_fill_hue
等多種,分別用來對畫布中的點線面進行不同的填充設色等。
n <- b + geom_bar(aes(fill = fl))
R中調色板設置n + scale_fill_brewer(palette = "Blues")
n + scale_fill_brewer(palette = "BrBG")
R中的灰色梯度顯示柱狀圖n + scale_fill_grey( start = 0.2, end = 0.8, na.value = "red")
通過 scale_fill_gradient顯示顏色過渡o <- a + geom_dotplot(aes(fill = ..x..))
o + scale_fill_gradient( low = "red", high = "yellow")
## `stat_bindot()` using `bins = 30`. Pick better value with `binwidth`.
通過scale_fill_gradient2顯示顏色過渡o + scale_fill_gradient2( low = "red", high = "blue", mid = "white", midpoint = 25 )
## `stat_bindot()` using `bins = 30`. Pick better value with `binwidth`.
選擇顏色序列o + scale_fill_gradientn(colours = terrain.colors(6) )
## `stat_bindot()` using `bins = 30`. Pick better value with `binwidth`.
其他可以選擇的顏色: rainbow(), heat.colors(), topo.colors(), cm.colors(), RColorBrewer::brewer.pal()
形狀繪製散點圖時,不同形狀的點表示分組,ggplot2已經儘可能做了最優化處理。以保證各組點的形狀都能做較好區分。如果要表示的分組數量太多,ggplot2會給出相應警告。
按照形狀分組 點圖標的選擇p <- f + geom_point(aes(shape = fl))
顯示空心圖標p + scale_shape(solid = FALSE)
指定點圖標p + scale_shape_manual(values = c(3:7))
更改圖標大小
q <- f + geom_point(aes(size = cyl))
q + scale_size_area()
每個圖形,只能設定一個坐標系。默認情況下,ggplot2使用平面直角坐標系。用戶可以指定使用極坐標coord_polar,也可以通過coord_trans,coord_flip等對坐標軸的刻度進行相應變換。
平面直角坐標系r <- b + geom_bar()
r + coord_cartesian(xlim = c(0, 5))
r + coord_fixed(ratio = 1/2)
橫軸縱軸調換r + coord_flip()
極坐標, 適用於繪製餅圖r + coord_polar(theta = "x", direction=1 )
橫軸、縱軸的變換,如 log, sqrt等r + coord_trans(y = "sqrt")
設定坐標軸範圍t + coord_cartesian(xlim = c(0, 100), ylim = c(10, 20))
## NULL
t + xlim(0, 100) + ylim(10, 20)
## NULL
細節調整 柱狀圖的疊加以及比較 並排排列s <- ggplot(mpg, aes(fl, fill = drv))
s + geom_bar(position = "dodge")
s + geom_bar(position = "stack")
按百分比堆疊排列, 各柱子等高s + geom_bar(position = "fill")
散點圖的隨機化在每個點的x,y方向上都加上較小的隨機值, 以便點能散開。
f + geom_point(position = "jitter")
繪圖主題所謂主題,就是繪圖的風格。通過設定圖形的主題,可以生成各種風格的圖形。
ggplot2自身提供了一些主題,如:
theme_grey()
theme_gray()
theme_bw()
theme_linedraw()
theme_light()
theme_dark()
theme_minimal()
theme_classic()
theme_void()
theme_test()
t <- ggplot(mpg, aes(cty, hwy)) + geom_point()
t + theme_grey()
t + theme_classic()
t + theme_minimal()
ggthemes程序包(https://jrnold.github.io/ggthemes/reference/index.html)提供了更多主題,加載後,即可與ggplot2混合使用。
theme_base(): 模擬plot()的風格
theme_calc(): LibreOffice Calc風格
theme_economist() : 經濟學家雜誌風格
theme_economist_white(): 經濟學家雜誌
theme_excel(): 微軟Office Excel傳統風格
theme_excel_new(): 微軟Office Excel最新風格
theme_few():Few’s 「Practical Rules for Using Color in Charts」
theme_fivethirtyeight(): Theme inspired by fivethirtyeight.com plots
theme_foundation()
theme_gdocs() : google文檔風格
theme_hc(): Highcharts Theme
theme_igray(): 逆向灰色梯度風格
theme_map(): 簡約地圖風格 Clean theme for maps
theme_pander() : A ggplot theme originated from the pander package
theme_par(): Theme which uses the current 『base』 graphics parameter values from par(). Not all par() parameters, are supported, and not all are relevant to ggplot2 themes.
theme_solarized() theme_solarized_2(): ggplot color themes based on the Solarized palette
theme_solid(): Theme with nothing other than a background color
theme_stata(): Stata統計軟體繪圖風格
theme_tufte():Tufte Maximal Data, Minimal Ink Theme
theme_wsj():華爾街日報風格 Wall Street Journal theme
更多細節調整,可以查看theme()函數。
圖形分面 facet當要按照某一個因子的不同水平,將每個水平分別展示在不同的圖形時,可以使用圖形分面。例如,各省份GDP的逐年變化,可以按照年份繪製多個地圖,每個小地圖(分面)只展示該年份的GDP即可。
t <- ggplot(mpg, aes(cty, hwy)) + geom_point()
t + facet_grid(. ~ fl)
t + facet_grid(year ~ .)
t + facet_grid(year ~ fl)
t + facet_wrap(~ fl)
t + facet_grid(. ~ fl, labeller = label_both)
t + facet_grid(. ~ fl, labeller = label_bquote(alpha ^ .(x)))
t + facet_grid(. ~ fl, labeller = label_parsed)
標題和坐標軸 更改標題和坐標軸名稱默認情況下,ggplot2繪製的圖形並沒有標題,添加標題,可以用ggtitle函數。
t + ggtitle("New Plot Title")
t + xlab("New X label")
t + ylab("New Y label")
t + labs(title =" New title", x = "New x", y = "New y")
ggtitle添加的標題默認是向左排列的,要設置標題居中,則用theme函數。
t + ggtitle("New Plot Title")+
theme(plot.title = element_text(hjust = 0.5))
t2 <- ggplot(mpg, aes(cty, hwy, color = trans)) + geom_point()
t2 + theme(legend.position = "bottom")
t2 + guides(color = "none")
t2 + scale_fill_discrete(name = "Title", labels = c("A", "B", "C"))
添加標註而在ggplot2中,使用的是annotate()。annotate可以添加,文字、多邊形或者任何其他geom對象。
繪製地圖 geom_mapdata <- data.frame(murder = USArrests$Murder,
state = tolower(rownames(USArrests)))
map <- map_data("state")
l <- ggplot(data, aes(fill = murder))
l + geom_map( aes(map_id = state), map = map ) +
expand_limits( x = map$long, y = map$lat )
library(maps)
thismap = map_data("world")
ggplot(thismap, aes(long, lat, group=group)) +
geom_polygon(fill="white", colour="gray") +
coord_map(projection = "ortho", orientation=c(41, -74, 0))
ggplot2 程序包還可以支持sf程序包的對象,geo_sf系列函數可以較為方便地生成地圖。
由於sf程序包的st_read, st_transform, st_as_sf提供了讀取和轉換空間數據的辦法,因此通過sf讀取和處理空間數據,用ggplot2進行可視化,不失為很好的選擇。
stat_sf()
geom_sf()
geom_sf_label()
geom_sf_text()
coord_sf()
ggplot2的ggsave函數,可以根據圖形的擴展名, 將ggplot2繪製的圖形保存為相應的文件格式,默認保存7×7英寸, 300dpi的圖形。
ggsave()
進一步閱讀http://www.cookbook-r.com/Graphs/
https://www.rstudio.com/resources/cheatsheets/
Hadley Wickham (2010). A layered grammar of graphics. Journal of Computational and Graphical Statistics, 19(1), 3-28.
Wilkinson, L. (2012). The grammar of graphics. In Handbook of Computational Statistics (pp. 375-414). Springer, Berlin, Heidelberg.
Wilkinson, L. (2011). ggplot2: Elegant Graphics for Data Analysis by WICKHAM, H. Biometrics, 67(2), 678-679.
Hadley Wickham (2007). Reshaping Data with the reshape Package. Journal of Statistical Software, 21(12), 1-20. http://www.jstatsoft.org/v21/i12/.
Hadley Wickham, Romain François, Lionel Henry and Kirill Müller (2019). dplyr: A Grammar of Data Manipulation. R package version 0.8.0.1. https://CRAN.R-project.org/package=dplyr