2.6繪制幾何圖形
您可能會(huì)猜測(cè),通過(guò)替換geom_point()其他的 geom 函數(shù),您會(huì)得到不同類型的圖形。這是一個(gè)很好的猜測(cè)!在以下部分中,您將了解 ggplot2 中提供的一些其他重要圖形類型。這不是一個(gè)詳盡的列表,但包含最常用的繪圖類型。你想了解跟多individual-geoms和collective-geoms。
- geom_smooth() 擬合數(shù)據(jù)的平滑曲線并顯示平滑曲線及其標(biāo)準(zhǔn)誤差。
- geom_boxplot()生成箱線圖來(lái)總結(jié)一組點(diǎn)的分布。
- geom_histogram()和geom_freqpoly()顯示連續(xù)變量的分布。
- geom_bar()`顯示了分類變量的分布。
- geom_path()和geom_line()在數(shù)據(jù)點(diǎn)之間畫線。折線圖從左到右行進(jìn)行的連線,而路徑圖可以朝任何方向行進(jìn)。折線圖通常用于探索事物如何隨時(shí)間變化。
2.6.1 在圖形中添加平滑曲線
如果您的散點(diǎn)圖包含大量噪聲,則很難看到主要模式。在這種情況下,geom_smooth()向圖中添加平滑線很有用:
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
geom_smooth()
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'

這將用平滑曲線覆蓋散點(diǎn)圖,包括以灰色顯示的各點(diǎn)置信區(qū)間的形式評(píng)估不確定性。如果您對(duì)置信區(qū)間不感興趣,請(qǐng)使用geom_smooth(se = FALSE)將其關(guān)閉。
method是[geom_smooth()](https://ggplot2.tidyverse.org/reference/geom_smooth.html)的一個(gè)重要參數(shù),它允許您選擇使用哪種類型的模型來(lái)擬合平滑曲線:
-
method = "loess",n 較小時(shí)的默認(rèn)值,使用平滑的局部回歸(如?loess中所述)。線條的平滑程度由span參數(shù)控制,范圍從 0(很不平滑)到 1(非常平滑)。ggplot(mpg, aes(displ, hwy)) + geom_point() + geom_smooth(span = 0.2) #> `geom_smooth()` using method = 'loess' and formula 'y ~ x' ggplot(mpg, aes(displ, hwy)) + geom_point() + geom_smooth(span = 1) #> `geom_smooth()` using method = 'loess' and formula 'y ~ x'imageimageLoess 不適用于大型數(shù)據(jù)集(內(nèi)存消耗是O(n2),因此在n超過(guò)1000是下使用另一種平滑算法。
-
method = "gam"可以調(diào)用mgcv 包提供的廣義可加模型。您需要先加載 mgcv,然后使用類似formula = y ~ s(x)或y ~ s(x, bs = "cs")(對(duì)于大數(shù)據(jù))的公式 。這就是 ggplot2 在超過(guò) 1000 個(gè)數(shù)據(jù)時(shí)使用。library(mgcv) ggplot(mpg, aes(displ, hwy)) + geom_point() + geom_smooth(method = "gam", formula = y ~ s(x))

-
method = "lm"擬合線性模型,默認(rèn)進(jìn)行線性擬合。ggplot(mpg, aes(displ, hwy)) + geom_point() + geom_smooth(method = "lm") #> `geom_smooth()` using formula 'y ~ x'image method = "rlm"工作原理類似于lm(),但使用了強(qiáng)大的擬合算法,因此異常值不會(huì)對(duì)擬合產(chǎn)生太大影響。它是MASS 包的一部分,所以記得先加載它。
2.6.2 箱線圖和擾動(dòng)點(diǎn)圖
當(dāng)一組數(shù)據(jù)包含分類變量和多個(gè)連續(xù)變量時(shí),您可能需要了解連續(xù)變量的值如何隨分類變量而變化。假設(shè)我們想了解具有相同動(dòng)力傳動(dòng)系統(tǒng)的汽車的耗油量如何變化。我們可以從這樣的散點(diǎn)圖開始:
ggplot(mpg, aes(drv, hwy)) +
geom_point()

因?yàn)?code>drv和hwy的取值很少,所以有很多過(guò)度繪制。許多點(diǎn)繪制在同一位置,很難看到分布。有三種有用的技術(shù)可以解決這個(gè)問(wèn)題:
擾動(dòng)點(diǎn)圖,geom_jitter(),為數(shù)據(jù)添加了一些隨機(jī)噪聲,這有助于避免過(guò)度重復(fù)。
箱線圖,geom_boxplot()用若干統(tǒng)計(jì)量概括數(shù)據(jù)分布情況。
小提琴圖,geom_violin()顯示了分布“密度”,突出數(shù)據(jù)分布密集的區(qū)域。
這些如下圖所示:
ggplot(mpg, aes(drv, hwy)) + geom_jitter()
ggplot(mpg, aes(drv, hwy)) + geom_boxplot()
ggplot(mpg, aes(drv, hwy)) + geom_violin()



每種方法都有其優(yōu)點(diǎn)和缺點(diǎn)。箱線圖僅用五個(gè)數(shù)字對(duì)分布進(jìn)行概括,而擾動(dòng)點(diǎn)圖顯示了每個(gè)點(diǎn),但僅適用于相對(duì)較小的數(shù)據(jù)集。小提琴圖提供了最豐富的信息,但依賴于密度估計(jì)的計(jì)算,這可能難以解釋。
對(duì)于擾動(dòng)點(diǎn)圖,geom_jitter()和geom_point()提供了圖形屬性作為控制:size,colour,和shape。對(duì)于geom_boxplot()和geom_violin(),您可以通過(guò)colour或fill控制輪廓和內(nèi)部顏色。
2.6.3 直方圖和頻率多邊形
直方圖和頻數(shù)多邊圖顯示單個(gè)數(shù)值變量的分布。與箱線圖相比,它們提供了更多關(guān)于單個(gè)組分布的信息,但占用內(nèi)存更大。
ggplot(mpg, aes(hwy)) + geom_histogram()
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
ggplot(mpg, aes(hwy)) + geom_freqpoly()
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.


直方圖和頻數(shù)多邊圖的工作方式相同:它們對(duì)數(shù)據(jù)進(jìn)行分箱,然后計(jì)算每個(gè)分箱中的觀察次數(shù)。唯一的區(qū)別是:直方圖使用條形顯示,頻率多邊形使用線條顯示。
您可以使用binwidth參數(shù)控制箱的寬度(如果您不想要均勻間隔的箱,您可以使用該breaks參數(shù))。分箱寬度是非常重要的。默認(rèn)值只是將您的數(shù)據(jù)分成 30 個(gè)箱,這可能不是最佳選擇。您應(yīng)該嘗試多個(gè) bin 寬度,并且您可能會(huì)發(fā)現(xiàn)需要多個(gè) bin 寬度來(lái)展示數(shù)據(jù)。
ggplot(mpg, aes(hwy)) +
geom_freqpoly(binwidth = 2.5)
ggplot(mpg, aes(hwy)) +
geom_freqpoly(binwidth = 1)


頻數(shù)多邊形的替代方法是密度圖,geom_density()。我不喜歡密度圖,因?yàn)樗鼈兏y解釋,因?yàn)榈讓佑?jì)算更復(fù)雜。密度圖的前提是要求基礎(chǔ)分布是連續(xù)的、無(wú)界的和平滑的。
要比較不同子組的分布,您可以將分類變量 (geom_histogram()) 或 (geom_freqpoly())映射到填充顏色。使用頻數(shù)多邊形比較分布更容易,因?yàn)榛A(chǔ)感知任務(wù)更容易。您也可以使用分面:這會(huì)使比較更困難一些,但更容易查看每個(gè)組的分布。
ggplot(mpg, aes(displ, colour = drv)) +
geom_freqpoly(binwidth = 0.5)
ggplot(mpg, aes(displ, fill = drv)) +
geom_histogram(binwidth = 0.5) +
facet_wrap(~drv, ncol = 1)


2.6.4 條形圖
離散變量情形下,條形圖與直方圖類似,使用geom_bar():
ggplot(mpg, aes(manufacturer)) +
geom_bar()

(修復(fù)標(biāo)簽鏈接中學(xué)習(xí)如何修復(fù)標(biāo)簽)。
條形圖可能會(huì)令人困惑,因?yàn)榘褍煞N截然不同的圖像通常都稱為條形圖。上面的表格是未經(jīng)過(guò)處理的數(shù)據(jù),每個(gè)觀察值對(duì)應(yīng)每個(gè)條的高度。另一種形式的條形圖用于預(yù)先處理的數(shù)據(jù)。例如,您有三種具有平均效果的藥物:
drugs <- data.frame(
drug = c("a", "b", "c"),
effect = c(4.2, 9.7, 6.1)
)
要顯示此類數(shù)據(jù),您需要修改geom_bar()默認(rèn)設(shè)置( 不讓stat 對(duì)數(shù)據(jù)進(jìn)行分類和計(jì)數(shù))。但是,使用geom_point()會(huì)更好,因?yàn)辄c(diǎn)比條占用的空間更少,并且不需要 y 軸包含 0。
ggplot(drugs, aes(drug, effect)) + geom_bar(stat = "identity")
ggplot(drugs, aes(drug, effect)) + geom_point()


2.6.5 時(shí)間序列中的折線圖和路徑圖
折線圖和路徑圖通常用于時(shí)間序列數(shù)據(jù)。折線圖從左到右連接點(diǎn),而路徑圖按照它們?cè)跀?shù)據(jù)集中出現(xiàn)的順序連接它們(換句話說(shuō),折線圖是按 x 值排序的數(shù)據(jù)的路徑圖)。折線圖通常在 x 軸上有時(shí)間,顯示單個(gè)變量如何隨時(shí)間變化。路徑圖顯示兩個(gè)變量如何隨時(shí)間同時(shí)變化,時(shí)間以觀測(cè)值的連接方式進(jìn)行編碼。
由于mpg數(shù)據(jù)集中的年份變量只有兩個(gè)值,我們將使用economics數(shù)據(jù)集顯示一些時(shí)間序列圖,其中包含過(guò)去 40 年測(cè)量的美國(guó)經(jīng)濟(jì)數(shù)據(jù)。下圖顯示了隨時(shí)間變化的兩個(gè)失業(yè)圖,均使用geom_line(). 第一個(gè)顯示失業(yè)率,而第二個(gè)顯示失業(yè)周數(shù)的中位數(shù)。我們已經(jīng)可以看到這兩個(gè)變量的一些差異,特別是在最后一個(gè)高峰期,失業(yè)率低于之前的高峰期,但失業(yè)的持續(xù)時(shí)間很長(zhǎng)。
ggplot(economics, aes(date, unemploy / pop)) +
geom_line()
ggplot(economics, aes(date, uempmed)) +
geom_line()


為了更詳細(xì)地研究這種關(guān)系,我們想在同一個(gè)圖上繪制兩個(gè)時(shí)間序列。我們可以繪制失業(yè)率與失業(yè)持續(xù)時(shí)間的散點(diǎn)圖,但是我們無(wú)法再看到隨時(shí)間的演變。解決方案是將時(shí)間上相鄰的點(diǎn)與線段連接起來(lái),形成路徑圖。
下面我們繪制失業(yè)率與失業(yè)時(shí)間的關(guān)系,并將個(gè)人觀察結(jié)果與一條路徑結(jié)合起來(lái)。由于有許多線交叉,在第一個(gè)圖中不容易看出時(shí)間流動(dòng)的方向。在第二個(gè)圖中,我們?yōu)辄c(diǎn)著色,以便更容易看到時(shí)間的方向。
ggplot(economics, aes(unemploy / pop, uempmed)) +
geom_path() +
geom_point()
year <- function(x) as.POSIXlt(x)$year + 1900
ggplot(economics, aes(unemploy / pop, uempmed)) +
geom_path(colour = "grey50") +
geom_point(aes(colour = year(date)))


我們可以看到失業(yè)率和失業(yè)時(shí)間高度相關(guān),但近年來(lái)失業(yè)時(shí)長(zhǎng)相對(duì)于失業(yè)率一直在增加。
對(duì)于縱向數(shù)據(jù),您通常希望在每個(gè)圖上顯示多個(gè)時(shí)間序列,每個(gè)序列代表一個(gè)人。為此,您需要將group圖形屬性映射到一個(gè)變量,該變量編碼每個(gè)觀察的組成員資格。
2.7 修改坐標(biāo)軸
后續(xù)將學(xué)習(xí)所有可用的選項(xiàng),但有兩個(gè)有用的最常見(jiàn)選項(xiàng)。xlab()和ylab()修改 x 和 y 軸標(biāo)簽:
ggplot(mpg, aes(cty, hwy)) +
geom_point(alpha = 1 / 3)
ggplot(mpg, aes(cty, hwy)) +
geom_point(alpha = 1 / 3) +
xlab("city driving (mpg)") +
ylab("highway driving (mpg)")
# Remove the axis labels with NULL
ggplot(mpg, aes(cty, hwy)) +
geom_point(alpha = 1 / 3) +
xlab(NULL) +
ylab(NULL)



ggplot(mpg, aes(drv, hwy)) +
geom_jitter(width = 0.25)
ggplot(mpg, aes(drv, hwy)) +
geom_jitter(width = 0.25) +
xlim("f", "r") +
ylim(20, 30)
#> Warning: Removed 139 rows containing missing values (geom_point).
# For continuous scales, use NA to set only one limit
ggplot(mpg, aes(drv, hwy)) +
geom_jitter(width = 0.25, na.rm = TRUE) +
ylim(NA, 30)



更改坐標(biāo)區(qū)范圍,區(qū)間之外的值被設(shè)置為NA。您可以使用na.rm = TRUE抑制相關(guān)警告,但要小心。如果您的繪圖計(jì)算匯總統(tǒng)計(jì)量(例如,樣本均值),則此轉(zhuǎn)換NA發(fā)生在計(jì)算匯總統(tǒng)計(jì)量之前,并且在某些情況下可能會(huì)導(dǎo)致不希望出現(xiàn)的結(jié)果。
2.8 輸出
大多數(shù)情況下,您創(chuàng)建一個(gè)繪圖對(duì)象并立即繪制它,但您也可以將繪圖保存到變量中并對(duì)其進(jìn)行操作:
p <- ggplot(mpg, aes(displ, hwy, colour = factor(cyl))) +
geom_point()
一旦你有了一個(gè)繪圖對(duì)象,你可以用它做一些事情:
-
顯示在屏幕上print()。這在交互式運(yùn)行時(shí)會(huì)自動(dòng)發(fā)生,但在循環(huán)或函數(shù)中,您需要手動(dòng)輸入print()完成。
print(p)image -
使用ggsave()將其保存到磁盤。
# Save png to disk ggsave("plot.png", p, width = 5, height = 5) -
用summary() 查看圖像結(jié)構(gòu)。
summary(p) #> data: manufacturer, model, displ, year, cyl, trans, drv, cty, hwy, fl, #> class [234x11] #> mapping: x = ~displ, y = ~hwy, colour = ~factor(cyl) #> faceting: <ggproto object: Class FacetNull, Facet, gg> #> compute_layout: function #> draw_back: function #> draw_front: function #> draw_labels: function #> draw_panels: function #> finish_data: function #> init_scales: function #> map_data: function #> params: list #> setup_data: function #> setup_params: function #> shrink: TRUE #> train_scales: function #> vars: function #> super: <ggproto object: Class FacetNull, Facet, gg> #> ----------------------------------- #> geom_point: na.rm = FALSE #> stat_identity: na.rm = FALSE #> position_identity -
使用saveRDS(), 將它的緩存副本保存到磁盤。 這將保存繪圖對(duì)象的完整副本,因此您可以輕松地使用readRDS()訪問(wèn).
saveRDS(p, "plot.rds") q <- readRDS("plot.rds")



