2.ggplot2——入門(二)

2.6繪制幾何圖形

您可能會(huì)猜測(cè),通過(guò)替換geom_point()其他的 geom 函數(shù),您會(huì)得到不同類型的圖形。這是一個(gè)很好的猜測(cè)!在以下部分中,您將了解 ggplot2 中提供的一些其他重要圖形類型。這不是一個(gè)詳盡的列表,但包含最常用的繪圖類型。你想了解跟多individual-geomscollective-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'
image.png

這將用平滑曲線覆蓋散點(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'
    
    image
    image

    Loess 不適用于大型數(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))
    
image.png
  • 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()
image

因?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()
image
image
image

每種方法都有其優(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ò)colourfill控制輪廓和內(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`.
image
image

直方圖和頻數(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)
image
image

頻數(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)
image
image

2.6.4 條形圖

離散變量情形下,條形圖與直方圖類似,使用geom_bar()

ggplot(mpg, aes(manufacturer)) + 
  geom_bar()
image

修復(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()
image
image

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()
image
image

為了更詳細(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)))
image
image

我們可以看到失業(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)
image
image
image

xlim()ylim()修改軸的限制:

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)
image
image
image

更改坐標(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")
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容