DC and Marvel


在繼續之前,let’s have some fun! 在這程式筆記中,我們將使用漫畫人物的資料集來回顧、介紹和練習 R 的內建函數。 ( 資料來源: Kaggle.com )




1. 讀入並檢查資料框的結構

🌻 read.csv() - 讀取CSV(逗號分隔值)的文件

D = read.csv("data/comics1.csv")

🌻 nrow() - 確認row的數量

nrow(D)
[1] 7250

🌻 ncol() - 確認column的數量

ncol(D)
[1] 9

資料框之中 …


🌻 str() - 用來檢查資料框的結構,每個column的資料種類

str(D)
'data.frame':   7250 obs. of  9 variables:
 $ publisher  : chr  "dc" "dc" "dc" "dc" ...
 $ name       : chr  "Batman (Bruce Wayne)" "Superman (Clark Kent)" "Green Lantern (Hal Jordan)" "James Gordon (New Earth)" ...
 $ align      : chr  "Good" "Good" "Good" "Good" ...
 $ eye        : chr  "Blue" "Blue" "Brown" "Brown" ...
 $ hair       : chr  "Black" "Black" "Brown" "White" ...
 $ sex        : chr  "Male" "Male" "Male" "Male" ...
 $ alive      : chr  "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 ...


🗿 QUIZ 1:
  ■ 這個資料框的名字是什麼?
  ■ 我們要分析的目標對象是什麼?
  ■ 我們感興趣的屬性是哪些?
  ■ 資料集有哪些是數值型的column ?
  ■ 資料集有哪些是字串型的column ?
  ■ …
  ■ 類別 欄位是什麼意思呢?
  ■ 哪些欄位是 類別 欄位呢?
  ■ 我們應該要把類別欄位轉成因素(factor)變數嗎?

🌷 回答這些問題之前,我們應該要先檢查欄位的內容



2. 檢查變數

🌻 summary() 是檢查資料框(每個column的)內容最方便的方式

summary(D)
  publisher             name              align               eye           
 Length:7250        Length:7250        Length:7250        Length:7250       
 Class :character   Class :character   Class :character   Class :character  
 Mode  :character   Mode  :character   Mode  :character   Mode  :character  
                                                                            
                                                                            
                                                                            
     hair               sex               alive            appearances  
 Length:7250        Length:7250        Length:7250        Min.   :   1  
 Class :character   Class :character   Class :character   1st Qu.:   3  
 Mode  :character   Mode  :character   Mode  :character   Median :   8  
                                                          Mean   :  42  
                                                          3rd Qu.:  26  
                                                          Max.   :4043  
      year     
 Min.   :1936  
 1st Qu.:1978  
 Median :1992  
 Mean   :1989  
 3rd Qu.:2004  
 Max.   :2013  

🌷 請注意,對不同資料種類的欄位,summary()會以不同的方式進行匯總

💡 分佈&統計量
分佈 : 是一種描述變數的方式,它描述著 …
  ◇ 變數值的變化
  ◇ 也就是說,變數的值是如何分佈的?
統計量 : 數值變數的某種具體特徵
  ◇ 舉例來說: 平均(mean), 中位數(median), 最小值(min), 最大值(max)
■ 變數的分佈可以用兩種型式表示 :
  ◇ 在數字上, 用統計量表示 或者
  ◇ 以圖形上,用繪圖的方式表示



2.1 檢查數值(連續)變數

🌻 mean(), median, max, min() - 取得數值變數的個別統計量

c( mean=mean(D$year), median=median(D$year), 
   max=max(D$year), min=min(D$year)  )
  mean median    max    min 
  1989   1992   2013   1936 

🌻 summary 一次獲得所有主要的統計量

summary(D$year)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   1936    1978    1992    1989    2004    2013 

🌻 hist() - 畫出數值變數的分佈
🌻 log() 當分佈很不均勻時,對數函數有助於壓制極端值的視覺衝擊

par(mfrow=c(1,2), mar=c(2,2,3,2), cex=0.6)  # 2 plots in a row, smaller font
hist(D$year, main="year")
hist(D$appearances, main="appearances")

log(D$appearances,10) %>% hist(main="log(appear.)")



2.2 檢查類別(離散型)變數

🌻 table() 列出並各類別的個數

table(D$align)

    Bad    Good Neutral 
   2915    3178    1157 

請注意,它是依類別名稱的字母順序排列

🌻 barplot() 視覺化離散變數的分佈

par(mfrow=c(1,1), cex=0.6)  # 1 plots in a row
table(D$align) %>% barplot(main="align")


🗿 QUIZ 2.2
  ■ 分佈是什麼意思?
  ■ 我們如何檢查 數值 變數的分佈?
  ■ 我們如何檢查 類別 變數的分佈?
  ■ 我們可以以統計量圖形檢查變數,哪種方式比較好呢?
  ■ …
  ■ 以統計量檢查變數 appearances
  ■ 以圖形方式檢查變數 year
  ■ 以統計量檢查變數 sex
  ■ 以圖形方式檢查變數 eye




3. 字串(Character) vs. 因素(Factor)

在R裡面,原始資料之中的字串欄位可以被儲存為因素(factor)或字串(character)變數, 這兩種變數之間可以相互轉換。 好比說,align這個欄位一開始是被當作字串變數讀入, 我們可以用以下的指令將其轉變為一個具有3個不同的類別(levels)的因素變數f.align

🌻 factor() - 將字串向量轉為因素向量

D$f.align = factor(D$align, levels=c("Good","Neutral","Bad"))

有需要的話,我們可以指定因素變數之中各類別(levels)的排列順序

par(mfrow=c(1,2), cex=0.7)  
table(D$align) %>% barplot(main="align")
table(D$f.align) %>% barplot(main="f.align")

我們將 eye也轉為因素變數

D$eye = factor(D$eye)

現在,它變成了 8 個類別(levels)的因素變數

str(D$eye)
 Factor w/ 8 levels "Black","Blue",..: 2 2 3 3 2 2 2 2 2 2 ...

🌻 level(x) 列出因素變數x之中的所有類別

levels(D$eye)
[1] "Black"  "Blue"   "Brown"  "Green"  "others" "Red"    "White"  "Yellow"

若我們在 factor() 中沒有指定 levels時,各類別將以英文字母的順序排列

table(D$eye) 

 Black   Blue  Brown  Green others    Red  White Yellow 
   619   2477   2210    664    359    423    291    207 

🌻 sort() 對向量進行(升冪)排列

par(mfrow=c(1,1), cex=0.7)  
table(D$eye) %>% sort(dec=T) %>% barplot

summary(D)
  publisher             name              align                eye      
 Length:7250        Length:7250        Length:7250        Blue   :2477  
 Class :character   Class :character   Class :character   Brown  :2210  
 Mode  :character   Mode  :character   Mode  :character   Green  : 664  
                                                          Black  : 619  
                                                          Red    : 423  
                                                          others : 359  
                                                          (Other): 498  
     hair               sex               alive            appearances  
 Length:7250        Length:7250        Length:7250        Min.   :   1  
 Class :character   Class :character   Class :character   1st Qu.:   3  
 Mode  :character   Mode  :character   Mode  :character   Median :   8  
                                                          Mean   :  42  
                                                          3rd Qu.:  26  
                                                          Max.   :4043  
                                                                        
      year         f.align    
 Min.   :1936   Good   :3178  
 1st Qu.:1978   Neutral:1157  
 Median :1992   Bad    :2915  
 Mean   :1989                 
 3rd Qu.:2004                 
 Max.   :2013                 
                              

🌷 在 summary() 中,因素 (或類別) 變數最多只會列出 6 筆資料,其他則歸類為 Other 。

💡字串 (Character) vs. 因素 (Factor)
■ 字串和因素都可以用於表示類別變數。
■ 雖然儲存和呈現的方式不盡相同,但大多數的情況兩者可以交換使用。
■ 某些類別 columns 可能會以字串的形式被讀入。
■ 所以,我們應該檢查每一 column 的變數型態。
■ 通常,我們只需維持它們的原樣,在必要時將它們轉換型態即可。




4. 排序 (Order) 和 篩選 (Filter)

如果我們想要列出出現次數(appearances)最多的10個漫畫人物 …

4.1 Sorting 和 Ordering 的區別

我們可以以降冪的方式(decreasing=T)對D$appearances進行sort()並 使用head()從向量中挑選出最前面10個值

sort(D$appearances, decreasing=T) %>% head(10)
 [1] 4043 3360 3093 3061 2961 2496 2258 2255 2072 2017

這樣我們可以看到D$appearances之中最大的10個數字,但 … 他們是誰呢?

🌻 sort(x)x的內容進行排序並返回結果
🌻 order(x)x的內容排序建立一個索引向量,(用來重新排序其他的物件)

D[order(D$appearances,decreasing=T), c("year","appearances","name")] %>% head(10)
     year appearances                                  name
2424 1962        4043             Spider-Man (Peter Parker)
2425 1941        3360       Captain America (Steven Rogers)
1    1939        3093                  Batman (Bruce Wayne)
2426 1974        3061 Wolverine (James \\"Logan\\" Howlett)
2427 1963        2961   Iron Man (Anthony \\"Tony\\" Stark)
2    1986        2496                 Superman (Clark Kent)
2428 1950        2258                   Thor (Thor Odinson)
2429 1961        2255            Benjamin Grimm (Earth-616)
2430 1961        2072             Reed Richards (Earth-616)
2431 1962        2017            Hulk (Robert Bruce Banner)

如此我們可以按順序看到前10名最常出現的角色的出現年分(year)、出現次數(appearances)和名稱 (name)。

4.2 有條件的進行篩選 (Order)

🌻 subset(x, 條件, select=y) 依照所給定的條件篩選row,並依欄位名稱選擇column

d = subset(D, alive=="Deceased" & sex=="Female", select=c("year","appearances","name"))
d[order(d$appearances, decreasing=T), ] %>% head(10)
     year appearances                          name
2450 1963        1107         Jean Grey (Earth-616)
2510 1965         384  Gwendolyne Stacy (Earth-616)
50   1999         301   Kendra Saunders (New Earth)
2569 1975         259     Moira Kinross (Earth-616)
2571 1972         257 Namorita Prentiss (Earth-616)
2597 1964         226        Karen Page (Earth-616)
85   1971         216         Big Barda (New Earth)
103  1971         177     Talia al Ghul (New Earth)
2650 1964         170              Hela (Earth-616)
2651 1976         170 Lilandra Neramani (Earth-616)

以上,我們可以看到前10名出現次數最多的已故女性角色。


🗿 QUIZ 4.2
■ 列出出現次數為前 10 名的金髮綠眼女性角色
■ 列出 5 個最出現次數最少的紅髮、紅眼男性的 year, publisher, align, 和 name



5. 計數和比例

📋 為每個程式碼區塊寫下註解,將其作為自己的筆記本。

5.1 使用邏輯運算式計算數量和比例

🌻 用 sum() 來計算一個邏輯向量裡面 TRUE 的個數

sum(D$align == "Good")
[1] 3178


🌻 用 mean() 來計算一個邏輯向量裡面 TRUE 的比例

mean(D$align == "Good")
[1] 0.4383


5.2 table()prop.table()

🌻 table() 列出一個向量裡各不同的值出現的次數

table(D$align)

    Bad    Good Neutral 
   2915    3178    1157 


🌻 prop.table() 將計數轉換成比例

table(D$align) %>% prop.table

    Bad    Good Neutral 
 0.4021  0.4383  0.1596 


如果我們在table()中放入兩個變數,會發生什麼事呢?

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


查看prop.table的線上說明(F1),它的margin這個參數的作用是什麼?

table(D$f.align, D$sex) %>% prop.table
         
           Female    Male
  Good    0.17434 0.26400
  Neutral 0.05959 0.10000
  Bad     0.09324 0.30883
table(D$f.align, D$sex) %>% prop.table(1)
         
          Female   Male
  Good    0.3977 0.6023
  Neutral 0.3734 0.6266
  Bad     0.2319 0.7681
table(D$f.align, D$sex) %>% prop.table(2)
         
          Female   Male
  Good    0.5329 0.3924
  Neutral 0.1821 0.1486
  Bad     0.2850 0.4590


我們來練習一下,

  • 資料中有多少個壞男人 ❓
  • 壞角色之中有多少比率是女的 ❓
  • 女性之中有多少比率是壞人 ❓


🏆 Group Competition Round 1


6. 分類統計與分群運算

6.1 分類統計

要回答上面最後兩個問題,分別需要做兩次table(); 實際上,我們有有更簡便的方法

🌻 tapply(value, group, fun)依據groupvaluefun

tapply(D$align == "Neutral", D$sex, sum)
Female   Male 
   432    725 

按性別計算中立的人數

tapply(D$align == "Neutral", D$sex, mean)
Female   Male 
0.1821 0.1486 

按性別統計中立的人的比例


我們來練習一下,

  • 每種頭髮顏色中女性的比例分別是多少 ❓
  • 女性之中,每種頭髮顏色各有多少人 ❓


🏆 Group Competition Round 2


6.2 順序統計

商務中常有一些不連續但有次序的變數,像是年代(decade)

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 

我們可以依decade算出中性角色的比例

v = tapply(D$align == "Neutral", D$decade, mean) %>% round(3); v
    3     4     5     6     7     8     9    10    11 
0.071 0.077 0.094 0.137 0.180 0.137 0.134 0.182 0.250 

如果把這些數據繪製為圖形,將更容易觀察出趨勢。

🌻 plot(x, y, type) 以不同的方式繪製x和y方向的數據

  • type="p" 散點圖(預設值)
  • type="l" 線形圖
  • type="b" 帶標記的線圖
  • 有關更多線型和參數,請參見線上說明(F1
# 繪製圖形序列以查看趨勢
par(mfcol=c(2,2), mar=c(3,3,2,1), cex=0.7)
v %>% barplot()               # 直條圖
plot(names(v), v)             # 散點圖
plot(names(v), v, type='l')   # 線形圖
plot(names(v), v, type='b', ylim=c(0,0.25)) # 帶標記的從零開始的線圖

以上哪以種方式比較容易看見正確的趨勢呢?


6.3 按分類排列的序列

tapply(value, group, function)可以一次接受多個分組變數,如

v = tapply(D$align=="Bad", list(D$sex, D$decade), mean) %>% round(3); v
           3     4     5     6     7     8     9    10    11
Female 0.125 0.156 0.312 0.198 0.255 0.266 0.352 0.288 0.250
Male   0.050 0.274 0.289 0.559 0.480 0.457 0.513 0.414 0.439

🌻 lines()在現有繪圖中添加一條線。例如,我們可以比較不同性別的壞角色比例的趨勢,如下所示。

par(mfrow=c(1,1), mar=c(3,3,2,1), cex=0.7)
plot(colnames(v),  v[1,], type="l", ylim=c(0,0.6), col="red", lwd=2,
     main = "按性別劃分的壞角色比例")                     # 添加標題
lines(colnames(v), v[2,], col="blue", lwd=2)              # 添加第二條線
abline(h=seq(0,0.6,0.1), v=seq(3,10,1), col='lightgray')  # 添加格線

確定前三種頭髮顏色…

h3 = table(D$hair) %>% sort %>% tail(3) %>% names; h3
[1] "Blond" "Brown" "Black"

看看前三種頭髮顏色的比例如何隨時間變化。

par(mfrow=c(1,1), mar=c(3,3,2,1), cex=0.7)
v = tapply(D$hair=="Black", D$decade, mean)
plot(names(v),v,type='l',lwd=2,col="black",ylim=c(0,0.45),
     main="前三種頭髮顏色的比例隨時間的變化")
abline(h=seq(0,0.5,0.1), v=seq(3,10,1), col='lightgray')  
v = tapply(D$hair=="Brown", D$decade, mean)
lines(names(v),v,type='l',lwd=2,col="brown")
v = tapply(D$hair=="Blond", D$decade, mean)
lines(names(v),v,type='l',lwd=2,col="gold")


🗿 QUIZ 6.3
現在輪到你了。請製作圖表以…
■ 檢查前三種眼睛顏色的比例趨勢
■ 依據漫畫公司性別去比較存活機率的趨勢



   dc.Female dc.Male marvel.Female marvel.Male
3     0.7143  0.6923        0.0000      0.8571
4     0.7273  0.5810        0.8261      0.7438
5     0.7273  0.7547        0.8000      0.7297
6     0.8485  0.7465        0.7564      0.7082
7     0.5909  0.6964        0.6923      0.7182
8     0.7782  0.6518        0.8034      0.7293
9     0.8219  0.6911        0.8037      0.7639
10    0.8382  0.7395        0.6951      0.6447
11    0.9062  0.8525        0.8100      0.7160