🏠 學習重點:
  ■ 條狀圖簡單易懂,是很重要的的分析、溝通工具
  ■ 點狀圖通常用在比較各分析對象
  ■ 條狀圖主要用在分類比較
  ■ ggplot的三種條狀圖
    ◇ geom_bar() : 類似 barplot()
    ◇ geom_col() : 類似 table() %>% barplot()
    ◇ geom_histogram() : hist()
  ■ 有兩個分類變數時,需要設定position來選擇比較的基礎
    "stack" : 比較大類總數
    "dodge" : 比較各細類數量
    "fill" : 比較細類比率



1. 三種不一樣的條狀圖

1.1 準備資料

載入 libraries,並預設繪圖參數

pacman::p_load(dplyr,ggplot2,plotly,gridExtra)
theme_set(theme_get() + theme(
  text=element_text(size=8), legend.key.size=unit(10,"points")
  ))

載入 comics 資料集

D = read.csv("data/comics1.csv",stringsAsFactors=F) %>% as_tibble
glimpse(D)
Rows: 7,250
Columns: 9
$ publisher   <chr> "dc", "dc", "dc", "dc", "dc", "dc", "dc", "dc", "dc", "dc"~
$ name        <chr> "Batman (Bruce Wayne)", "Superman (Clark Kent)", "Green La~
$ align       <chr> "Good", "Good", "Good", "Good", "Good", "Good", "Good", "G~
$ eye         <chr> "Blue", "Blue", "Brown", "Brown", "Blue", "Blue", "Blue", ~
$ hair        <chr> "Black", "Black", "Brown", "White", "Black", "Black", "Blo~
$ sex         <chr> "Male", "Male", "Male", "Male", "Male", "Female", "Male", ~
$ alive       <chr> "Living", "Living", "Living", "Living", "Living", "Living"~
$ appearances <int> 3093, 2496, 1565, 1316, 1237, 1231, 1121, 1095, 1075, 1028~
$ year        <int> 1939, 1986, 1959, 1987, 1940, 1941, 1941, 1989, 1969, 1956~

tibbledplyr 中,被定義為增強型的資料框。

1.2 三種條狀圖

🌻 ggplot之中,有三種條狀圖可以使用

  • geom_histogram 顯示連續變數的 分布
  • geom_bar 顯示離散變數 的計數 (分布)
  • geom_col 顯示 / 比較 不同類別間的統計數據。
g1 = ggplot(D, aes(x=year)) + geom_histogram(binwidth=10)
g2 = ggplot(D, aes(x=align)) + geom_bar()
g3 = group_by(D, sex) %>% 
  summarise( casualty.ratio = mean(alive=="Deceased") ) %>%
  ggplot(aes(x=sex, y=casualty.ratio)) + geom_col()
grid.arrange(g1,g2,g3,nrow=1)  # align three plots in a row 

🌻 這些條狀圖有助於我們做分類比較

  • 幾十年來,新角色的數量
  • 好人、壞人,以及中立角色的數量
  • 男性角色和女性角色平均的傷亡率



2. 兩類別、大類與細類比較

只要在aes()之中將fill屬性對應到細類變數, 我們就可以在條狀圖的大類之中,以顏色區分細類。

g1 = ggplot(D, aes(x=year, fill=publisher)) + geom_histogram(binwidth=10)
g2 = ggplot(D, aes(x=align, fill=sex)) + geom_bar()
grid.arrange(g1,g2,nrow=1)  # align three plots in a row 

🚴 EXERCISE :

請試著修改以下程式碼來製作下面的圖表。

# group_by(D, sex) %>% 
#   summarise( casualty.ratio = mean(alive=="Deceased") ) %>%
#   ggplot(aes(x=sex, y=casualty.ratio)) + geom_col()

QUIZ :

根據以上圖表



3. 比較的基礎

3.1 列聯表 (Contingency Table)

類別間的比較是基於一種名為 列聯表 的資料結構。

table(D$align, D$sex)
         
          Female Male
  Bad        676 2239
  Good      1264 1914
  Neutral    432  725


3.2 列聯表的長型資料格式

然而,ggplot 並不採用表格型式。 為了和 aes() 這一配對繪圖相容, 我們需要準備 長型資料格式 的數據。

在製作長型資料格式時,count()group_by() %>% summarise() 更容易操作。

count(D, align, sex)
# A tibble: 6 x 3
  align   sex        n
  <chr>   <chr>  <int>
1 Bad     Female   676
2 Bad     Male    2239
3 Good    Female  1264
4 Good    Male    1914
5 Neutral Female   432
6 Neutral Male     725


3.3 設置 position 來改變比較的基礎

透過在 geom_col() 中設置 position 這一參數,我們可以用不同方式排列和比較表格中的數據。

dx = count(D, align, sex)
gg = lapply(c("stack","dodge","fill"), function(pos) {
  ggplot(dx, aes(sex,n,fill=align)) + 
    geom_col(position=pos, alpha=0.6) + labs(title=pos,y="")
  }) 
grid.arrange(grobs=gg, nrow=1)

🌻 不同的圖表有不同的用途…

  • stack 該數據強調性別的總合
  • dodge 比較表格中所有的數據
  • fill 將數據轉換為比例,以進行相對性的比較


QUIZ :
上述三個圖表中,哪個比較容易…

  • 依照性別分類,比較「中立」角色的數量
  • 依照性別分類,比較「中立」角色的比例
  • 比較各性別的總人數


🚴 EXERCISE :
事實上,我們可以用完全相同的數據再繪製三個圖表。 請試著修改以下程式碼來製作下面的圖表。

# gg = lapply(c("stack","dodge","fill"), function(pos) {
#   ggplot(dx, aes(sex,n,fill=align)) + 
#     geom_col(position=pos, alpha=0.6) + labs(title=pos,y="")
#   }) 
# grid.arrange(grobs=gg, nrow=1)



4. 條形圖的分析能力

讓我們在 D 資料集中,新增一個名為 decade 的欄位。

D = mutate(D, decade = (D$year -1900) %/% 10)
table(D$decade)

   3    4    5    6    7    8    9   10   11 
  28  271  106  678  823 1304 1581 1803  656 
4.1 窗格功能 facet

好壞人的數量如何隨年代而變 ❓ 好壞人數量的變化趨勢是否因性別、出版商而異 ❓

facet_grid(var1~var2)可以就每一種(v1,v2)的組合畫一個窗格

ggplot(D, aes(x=decade, fill=align)) + 
  geom_bar() + facet_grid(sex~publisher)  

我們用兩行簡單的程式碼就可以回答這些看似複雜繁瑣的問題了!

通常,比例會比數量更能反映出趨勢,欲把數字轉換為比例, 我們只需要將 position='fill 放在 geom_bar() 中。

# here we convert `align` into a factor so we can 
# re-order the align levels in a desirable way
D2 = D %>% mutate(
  align=factor(align,levels=c("Bad","Neutral","Good"))
  ) %>% 
  filter(decade >= 6) 
ggplot(D2, aes(x=decade, fill=align)) + 
  geom_bar(position="fill") +   
  facet_grid(sex~publisher)

4.2 比例 vs. 數量

下面是一個條形圖,顯示了在不同頭髮顏色和不同眼睛顏色的搭配中,好人和壞人所佔的比例。

hx = count(D2, hair, sort=T)
ex = count(D2, eye, sort=T)
D2 %>% filter(
  hair%in%hx$hair[1:3], eye%in%ex$eye[1:3], 
  align!="Neutral") %>% 
  ggplot(aes(decade,fill=align)) + 
  geom_bar(position="fill",alpha=0.7) +
  labs(x="eye",y="hair") +
  facet_grid(hair~eye)

🚴 EXERCISE :
你可以試著修改上面的程式碼

  • 繪製數字而不是比率嗎?
  • 你發現了什麼呢?
  • 在這個 exercise 中,你學到了什麼呢?