學習目標

單元範例設定

knitr::opts_chunk$set(echo = TRUE)
# 本章需要套件
library(tidyverse)
library(dataskills)
library(plotly)  # 製造互動式統計圖
library(cowplot)  # 製造組合式統計圖
set.seed(30250) # 設定隨機種子

檢視變項種類

data("pets")
glimpse(pets)
## Rows: 800
## Columns: 6
## $ id      <chr> "S001", "S002", "S003", "S004", "S005", "S006", "S007", "S008"~
## $ pet     <fct> dog, dog, dog, dog, dog, dog, dog, dog, dog, dog, dog, dog, do~
## $ country <fct> UK, UK, UK, UK, UK, UK, UK, UK, UK, UK, UK, UK, UK, UK, UK, UK~
## $ score   <int> 90, 107, 94, 120, 111, 110, 100, 107, 106, 109, 85, 110, 102, ~
## $ age     <int> 6, 8, 2, 10, 4, 8, 9, 8, 6, 11, 5, 9, 1, 10, 7, 8, 1, 8, 5, 13~
## $ weight  <dbl> 19.78932, 20.01422, 19.14863, 19.56953, 21.39259, 21.31880, 19~
levels(pets$pet)
## [1] "dog"    "cat"    "ferret"
levels(pets$country)
## [1] "UK" "NL"

檢視pets的六個變項的資料型態,屬於那種變項尺度?(建議暫停影片)

  • 連續變項 Continuous variables:“score”, “age”,“weight”

  • 間斷/類別變項 Discrete (or categorical) variables: “pet”,“country”

    • 名義變項 nominal variables:“pet”,“country”
    • 次序變項 ordinal variables: NA

基本繪圖

R基本繪圖函式 plot() 思維:在即定框架內一體成形 用途:初窺資料模式;規劃分析策略

柱狀圖

plot(x = pets$pet)
plot() with categorical x

plot() with categorical x

柱狀圖告訴我們的事:

箱型圖

plot(x = pets$pet, y = pets$score)

箱型圖告訴我們的事:

散佈圖

plot(x = pets$age, y = pets$weight)

散佈圖告訴我們的事:

直方圖

hist(pets$score, breaks = 20)

直方圖告訴我們的事:

改變breaks的數值,觀察輸出直方圖的變化。

ggplot運用示範

思維:繪圖如製作蛋糕,一層一層堆疊素材 用途:製作展示用的統計圖

預備畫布

ggplot()

設定基本佈局

mapping <- aes(x = pet, 
               y = score, 
               colour = country, 
               fill = country)
ggplot(data = pets, mapping = mapping)

繪製統計圖

ggplot(pets, aes(pet, score, colour = country, fill = country)) +
  geom_violin(alpha = 0.5) +
  labs(x = "Pet type",
       y = "Score on an Important Test",
       colour = "Country of Origin",
       fill = "Country of Origin",
       title = "My first plot!") +
  theme_bw(base_size = 15)

建議測試: - 改變alpha,base_size的數值,觀察輸出效果 - 更改labs()各參數的英文詞,觀察輸出效果

ggplot繪製基本統計圖

柱狀圖

適用:類別變項資料計數。

對照基本繪圖:柱狀圖

ggplot(pets, aes(pet)) +
  geom_bar()
Bar plot

Bar plot

箱型圖

適用:連續變項資料次數分佈,依類別變項分組呈現。

對照基本繪圖:箱型圖

ggplot(pets, aes(pet, score, fill=pet)) +
  geom_boxplot(alpha = 1)
Box plot

Box plot

散佈圖

適用:呈現來自相同的觀察單位,兩種連續變項資料的次數分佈。

對照基本繪圖:散佈圖

ggplot(pets, aes(age, score, color = pet)) +
  geom_point(alpha=0.5)
Scatter plot using geom_point()

Scatter plot using geom_point()

直方圖

適用:呈現一種連續變項資料的次數分佈;可判別變異趨勢;樣本數越多越清楚。

對照基本繪圖:直方圖

ggplot(pets, aes(score)) +
  geom_histogram(binwidth = 5, fill = "white", color = "black")
Histogram

Histogram

搭配參數fillposition,一張直方圖可呈現分組資料分佈。

ggplot(pets, aes(score, fill=pet)) +
  geom_histogram(binwidth = 5, alpha = 0.5, 
                 position = "dodge")
Grouped Histogram

Grouped Histogram

建議測試

將參數position的值改成“identity”, “fill”, “dodge”, 或 “stack”,觀察輸出效果。

分佈密度圖

適用:呈現一種連續變項資料的次數分佈;可判別變異趨勢;樣本數上千越清楚。

ggplot(pets, aes(score)) +
  geom_density()
Density plot

Density plot

搭配參數group,fillcolor,一張分佈密度圖可呈現分組資料分佈。

ggplot(pets, aes(score, fill = pet)) +
  geom_density(alpha = 0.5)
Grouped density plot

Grouped density plot

Try changing the alpha argument to figure out what it does.

建議測試
改變alpha的數值,觀察輸出效果

次數折線圖

適用:呈現一種連續變項資料的次數分佈;可判別變異趨勢;樣本數上千越清楚。

ggplot(pets, aes(score, color = pet)) +
  geom_freqpoly(binwidth = 5)
Frequency ploygon plot

Frequency ploygon plot

Try changing the binwidth argument to 5 and 0.1. How do you figure out the right value?

建議測試
改變binwidth的數值,觀察輸出效果

小提琴圖

小提琴圖是比箱型圖更直觀的資料次數分佈圖,非常態資料分佈一目了然。

ggplot(pets, aes(pet, score, fill=pet)) +
  geom_violin(draw_quantiles = .5,
              trim = FALSE, alpha = 0.5,)
Violin plot

Violin plot

建議測試
改變draw_quantile的數值,從0.1到0.9皆可,觀察輸出效果

分組統計柱狀圖

適用:使用函式stat_summary, geom_bar, geom_col, geom_col,將分組統計值轉化為柱狀圖的元素。

ggplot(pets, aes(pet, score, fill=pet)) +
  stat_summary(fun = mean, geom = "col", alpha = 0.5) + 
  stat_summary(fun.data = mean_se, geom = "errorbar",
               width = 0.25) +
  coord_cartesian(ylim = c(80, 120))
Column plot

Column plot

建議測試
改變coord_cartesian的數值,觀察輸出效果

組間區間

分組描述統計的重要資訊是集中量數(平均值)與誤差範圍(標準差、信賴區間)。以下分組箱形圖的箱子高度,代表距離平均值一個標準差的數值。

ggplot(pets, aes(pet, score, color=pet)) +
  stat_summary(fun.data = mean_se, geom = "crossbar") +
  stat_summary(fun.min = function(x) mean(x) - sd(x),
               fun.max = function(x) mean(x) + sd(x),
               geom = "errorbar", width = 0) +
  theme(legend.position = "none") # gets rid of the legend

以下R程式碼計算分組平均值與標準誤(standard error)。

pets_sum <- pets %>%
  group_by(pet) %>%
  summarize(mean = mean(score), se = sd(score)/sqrt(n()))
petsgg <- ggplot(pets_sum, aes(pet, mean, 
                      ymin = mean-se, 
                      ymax = mean+se))

以箱形呈現標準誤區間

petsgg + geom_crossbar()

以誤差線呈現標準誤區間

petsgg + geom_errorbar()

以直線呈現標準誤區間

petsgg + geom_linerange()

以點線呈現標準誤區間

petsgg + geom_pointrange()

迴歸線

散佈圖包含不只一組資料時,加上迴歸線能呈現分組的資料分佈趨勢。

ggplot(pets, aes(age, score, color = pet)) +
  geom_smooth(formula = y ~ x, method="lm")
Line plot using geom_smooth()

Line plot using geom_smooth()

建議測試
查詢geom_smooth有關method的說明,了解還有那些選項,觀察各種選項的輸出效果

ggplot自訂統計圖

ggplot的自訂函式,能改變統計圖的標籤文字、配色、以及畫布主題。

自訂標籤

方法一:使用labs()一次設定所有標籤

ggplot(x_vs_y, aes(x, y)) + geom_smooth(method=“lm”) + labs(title = “My Plot Title”, x = “The X Variable”, y = “The Y Variable”)

ggplot(pets, aes(age, score, color = pet)) +
  geom_smooth(formula = y ~ x, method="lm") +
  labs(title = "Pet score with Age",
       x = "Age (in Years)",
       y = "score Score",
       color = "Pet Type")

方法二:使用ggtitle,xlab(),ylab()設定各部位標籤

ggplot(x_vs_y, aes(x, y)) + geom_smooth(method=“lm”) + ggtitle(“My Plot Title”) + xlab(“The X Variable”) + ylab(“The Y Variable”)

ggplot(pets, aes(age, score, color = pet)) +
  geom_smooth(formula = y ~ x, method="lm") +
  ggtitle("Pet score with Age") +
  xlab("Age (in Years)") +
  ylab("score Score") +
  scale_color_discrete(name = "Pet Type")

自訂配色

ggplot提供scale_colour_manual(),scale_fill_manual()等函式設定線條或區塊的配色,配色選項可參考Colours chapter in Cookbook for R。建議更改下圖的配色數值,觀察輸出效果。

ggplot(pets, aes(pet, score, colour = pet, fill = pet)) +
  geom_violin() +
  scale_color_manual(values = c("darkgreen", "dodgerblue", "orange")) +
  scale_fill_manual(values = c("#CCFFCC", "#BBDDFF", "#FFCC66"))
Set custom colour

Set custom colour

自訂畫布主題

下圖是使用ggplot內建的主題minimal呈現的效果。

ggplot(pets, aes(age, score, color = pet)) +
  geom_smooth(formula = y ~ x, method="lm") +
  theme_minimal(base_size = 18)

如果有特殊需求,使用者可以自建主題,以下是Lisa DeBrunie提供的vampire theme。如果你想建立個人風格的主題,可以嘗試更改各部份配色與字型大小,建立符合你的統計圖主題。

vampire_theme <- theme(
  rect = element_rect(fill = "black"),
  panel.background = element_rect(fill = "black"),
  text = element_text(size = 20, colour = "white"),
  axis.text = element_text(size = 16, colour = "grey70"),
  line = element_line(colour = "white", size = 2),
  panel.grid = element_blank(),
  axis.line = element_line(colour = "white"),
  axis.ticks = element_blank(),
  legend.position = "top"
)

theme_set(vampire_theme)

ggplot(pets, aes(age, score, color = pet)) +
  geom_smooth(formula = y ~ x, method="lm")

匯出統計圖

有需要匯出製作好的統計圖,將ggplot存入物件,使用ggsave()使定匯出檔案名稱即可。如果你要指定輸出圖像的寛度與高度,ggsave()可設定統計圖的widthheight,單位有“in”, “cm”, “mm”。

box <- ggplot(pets, aes(pet, score, fill=pet)) +
  geom_boxplot(alpha = 0.5)

violin <- ggplot(pets, aes(pet, score, fill=pet)) +
  geom_violin(alpha = 0.5)

ggsave("demog_violin_plot.png", width = 5, height = 7)

ggsave("demog_box_plot.jpg", plot = box, width = 5, height = 7)

The file type is set from the filename suffix, or by specifying the argument device, which can take the following values: “eps”, “ps”, “tex”, “pdf”, “jpeg”, “tiff”, “png”, “bmp”, “svg” or “wmf”.

ggplot複合統計圖

結合小提琴圖與箱形圖

箱形圖能用來標記中位數與四分位區間。

ggplot(pets, aes(pet, score, fill = pet)) +
  geom_violin(show.legend = FALSE) + 
  geom_boxplot(width = 0.2, fill = "white", 
               show.legend = FALSE)  ## 通常不需顯示標籤
Violin-box plot

Violin-box plot

結合小提琴圖與區間線

stat_summary() 內置的函式將在第七單元學習。

ggplot(pets, aes(pet, score, fill=pet)) +
  geom_violin(trim = FALSE, alpha = 0.5) +
  stat_summary(
    fun = mean,
    fun.max = function(x) {mean(x) + sd(x)},
    fun.min = function(x) {mean(x) - sd(x)},
    geom="pointrange"
  )
Point-range plot using stat_summary()

Point-range plot using stat_summary()

結合小提琴圖與散佈圖

當樣本資料數目不多, geom_jitter 可用資料點顯示資料分佈。

# sample_n chooses 50 random observations from the dataset
ggplot(sample_n(pets, 50), aes(pet, score, fill=pet)) +
  geom_violin(
    trim = FALSE,
    draw_quantiles = c(0.25, 0.5, 0.75), 
    alpha = 0.5
  ) + 
  geom_jitter(
    width = 0.15, # points spread out over 15% of available width
    height = 0, # do not move position on the y-axis
    alpha = 0.5, 
    size = 3
  )
Violin-jitter plot

Violin-jitter plot

散佈圖內置廻歸線

當分資料分組不多,如五組之內,在散佈圖內繪製迴歸線有助了解資料分佈。

ggplot(sample_n(pets, 50), aes(age, weight, colour = pet)) +
  geom_point() +
  geom_smooth(formula = y ~ x, method="lm")
Scatter-line plot

Scatter-line plot

並列統計圖

cowplot套件可並列兩個以上ggplot,在同一張畫布之內。如以下plot_grid()的示範。

註:由於R環境設定問題,示範網頁無法展示並列統計圖。

疊加間斷變數的組合統計圖

調整透明度

資料點太多時,使用alpha調整散佈圖資料點的透明度,運用colour區分組別。

ggplot(pets, aes(age, score, colour = pet)) +
  geom_point(alpha = 0.25) +
  geom_smooth(formula = y ~ x, method="lm")
Deal with overlapping data using transparency

Deal with overlapping data using transparency

點面積散佈圖

資料點太多時,使用geom_count()調整散佈圖資料點的面積,表現各資料點的累積次數。

ggplot(pets, aes(age, score, colour = pet)) +
  geom_count()
Deal with overlapping data using geom_count()

Deal with overlapping data using geom_count()

另一種方法是使用色彩突顯每個資料點的累積次數。scale_color_viridis_c()viridis package套件的函式,可讓連續變項的數值,轉換為對應的色彩。

pets %>%
  group_by(age, score) %>%
  summarise(count = n(), .groups = "drop") %>%
  ggplot(aes(age, score, color=count)) +
  geom_point(size = 2) +
  scale_color_viridis_c()
Deal with overlapping data using dot colour

Deal with overlapping data using dot colour

疊加連續變數的組合統計圖

當統計圖只呈現兩種連續變項,過多資料點無法看出重要資訊。

ggplot(pets, aes(age, score)) +
  geom_point()
Overplotted data

Overplotted data

2維密度圖

運用 geom_density2d() 就能產生像等高線的空照密度圖。

ggplot(pets, aes(age, score)) +
  geom_density2d()
Contour map with geom_density2d()

Contour map with geom_density2d()

使用 stat_density_2d(aes(fill = ..level..), geom = "polygon") 可加上配色,強調次數密度差異。

ggplot(pets, aes(age, score)) +
  stat_density_2d(aes(fill = ..level..), geom = "polygon") +
  scale_fill_viridis_c()
Heatmap-density plot

Heatmap-density plot

2維直方圖

使用 geom_bin2d()可繪製像素化的密度圖。設定 binwidth 決定每塊像素的範圍。

ggplot(pets, aes(age, score)) +
  geom_bin2d(binwidth = c(1, 5))
Heatmap of bin counts

Heatmap of bin counts

蜂巢熱點圖

使用 geomhex() 可繪製蜂巢化的密度圖。 調整 binwidth, xlim(), ylim() 可決定蜂巢的格局

ggplot(pets, aes(age, score)) +
  geom_hex(binwidth = c(1, 5))
Hexagonal heatmap of bin counts

Hexagonal heatmap of bin counts

相關熱點圖

相關熱點圖用在呈現兩種類別變項分佈的相關係。繪製熱點圖首先要轉換資料,以下用到的 gather()將在第四及第五單元學習。

heatmap <- pets %>%
  select_if(is.numeric) %>% # get just the numeric columns
  cor() %>% # create the correlation matrix
  as_tibble(rownames = "V1") %>% # make it a tibble
  gather("V2", "r", 2:ncol(.)) # wide to long (V2)

轉換後的資料就能運用ggplot繪製基本統計圖,再使用geom_tile()轉換為統計圖。

ggplot(heatmap, aes(V1, V2, fill=r)) +
  geom_tile() +
  scale_fill_viridis_c()
Heatmap using geom_tile()

Heatmap using geom_tile()

互動式統計圖

plotly套件用來產生互動式統計圖。 運用 ggplotly()讓ggplot物件動起來。

demog_plot <- ggplot(pets, aes(age, score, fill=pet)) +
  geom_point() +
  geom_smooth(formula = y~x, method = lm)

ggplotly(demog_plot)

Interactive graph using plotly