1 課程目標

本週上課將介紹R的資料型態與資料結構,也就是R可以讀取並進行運算的對象,例如我們用 c() 來表示數字、文字的集合:

A<-c("台北市","新北市", "桃園市", "台中市","台南市","高雄市")
print(A)

[1] “台北市” “新北市” “桃園市” “台中市” “台南市” “高雄市”

B<-c(0,1,2,3,4,5,6,7,8,9)
print(B)

[1] 0 1 2 3 4 5 6 7 8 9 A是文字而B是數字的集合,另外還有邏輯以及日期等常用的資料型態。


R資料結構可分為一維、二維、多維:

2 資料型態

2.1 數值(numeric)

  • 數值可分為數值(numeric)或者是整數(integer)。任意數例如:
  • X<-c(2, 4, 6, 8); X

    [1] 2 4 6 8

    class(X)

    [1] “numeric”

    str(X)
    num [1:4] 2 4 6 8
  • \(\texttt{class()}\)函式告訴我們該資料型態或者是結構的屬性。
  • 可以用科學符號表示比較大的數字:
  • y=c(1.1e+06); y

    [1] 1100000

    class(y)

    [1] “numeric”

  • 整數則為:
  • u<-as.integer(c(4)); class(u)
    [1] “integer”
  • 整數是數值的子集合,因為整數的最大值是2147483647,遠小於數值的最大值。在一般運算或是統計上幾乎沒有差異,唯一的差別在於整數的儲存佔用空間比較小,而一般數值其實帶有小數點,只是沒有顯示,稱為浮點運算。由於電腦使用二進位制的運算,由一個有效數字加上冪數來表示,以這種表示法表示的數值,稱為浮點數。利用浮點進行運算,稱為浮點計算,也就是所有渉及小數的運算。。
  • 請輸入以下指令:
  • 乍看之下100應該是整數,但是其實是數值。
  • 又例如:
  • a<-c(7, 8.5, 9); class(a)

    [1] “numeric”

    b<-as.integer(a); b
    [1] 7 8 9
  • \(\texttt{as.integer()}\)傳回整數。
  • 變數如果與另一個變數對應條件時,R會顯示變數性質與對應結果:
  • h<-c(100, 200, 500)
    ok<-h>300
    b[ok]

    [1] 9

    ok<-h>1000
    b[ok]

    integer(0)

    2.2 字串(character)

  • 變數可以是字串,例如受訪者的性別、學生的姓名、國家名稱等等。
  • 請輸入:
  • state.abb
    class(state.abb)
  • 文字對於資料使用者而言相對於數值容易理解,但是用途比較受限,無法進行數學運算,但是在資料視覺化時相當有用,例如圖 2.1 顯示各州的人口數:
  • 美國各州人口數的點狀圖

    Figure 2.1: 美國各州人口數的點狀圖

  • 2.2 則重新排序各州的人口數:
  • 各州人口排序後的點狀圖

    Figure 2.2: 各州人口排序後的點狀圖

  • state.x77是矩陣,所以取出這個矩陣中的人口此一欄位,然後與state.abb結合成一個資料框,再以dotplot或者dotchart指令畫成點狀圖。
  • 數字也可以當成文字,例如我們分配第一位來上課的人到第1組、第二位第2組,總共分成5組,下課時規定第1組要關門窗,第2組倒垃圾等等:
  • char1<-c("1","2","3","4","5"); char1

    [1] “1” “2” “3” “4” “5”

    char2<-c(1, 2, "文字"); char2
    [1] “1” “2” “文字”
  • 數字都被視為字串,無法進行數學運算。字串無法用as.numeric轉換為數字,但是可以用語法進行轉換(請見因素一節)。
  • 數字經常會被誤認為字串。例如,我們到政府開放資料網站下載一筆資料稱為opendata106N0101.csv。 \(\texttt{str()}\)函式可以顯示資料中的變數性質。 :
  • library(foreign); library(tidyverse)
    file<-here::here('data','opendata106N0101.csv')
    opendf<-read.csv(file, header=T,
                     sep=',')
    str(opendf)
    ## 'data.frame':    375 obs. of  4 variables:
    ##  $ code      : chr  "新北市板橋區" "新北市三重區" "新北市中和區" "新北市永和區" ...
    ##  $ 年底人口數: chr  "551480" "387484" "413590" "222585" ...
    ##  $ 土地面積  : num  23.14 16.32 20.14 5.71 19.74 ...
    ##  $ 人口密度  : chr  "23835" "23747" "20532" "38956" ...
    file<-here::here('data','opendata106N0101.csv')
    dat<-read.csv(file, header=T, stringsAsFactors = F)
    nrow(dat) #check how many rows; n=375

    [1] 375

    dat <- dat[-c(369:375),] #delete the rows of small islands and notes
    head(dat, n=3)
          code 年底人口數 土地面積 人口密度
    1 新北市板橋區 551480 23.14 23835 2 新北市三重區 387484 16.32 23747 3 新北市中和區 413590 20.14 20532
  • 可以看到,新的資料中,變數code被認為是是字串,但是年底人口數、人口密度也被認為是字串。我們創造一個新的數字變數來取代字串變數:
  • dat <- dat %>% mutate(popu=as.numeric(年底人口數))
    str(dat)
    ## 'data.frame':    368 obs. of  5 variables:
    ##  $ code      : chr  "新北市板橋區" "新北市三重區" "新北市中和區" "新北市永和區" ...
    ##  $ 年底人口數: chr  "551480" "387484" "413590" "222585" ...
    ##  $ 土地面積  : num  23.14 16.32 20.14 5.71 19.74 ...
    ##  $ 人口密度  : chr  "23835" "23747" "20532" "38956" ...
    ##  $ popu      : num  551480 387484 413590 222585 416524 ...

    2.3 因素(factor)

  • 有些資料具有類別,例如性別、是或否、地區等等。Verzani (p.10) 的例子:
  • x=c("Yes","No","No","Yes","Yes"); x

    [1] “Yes” “No” “No” “Yes” “Yes”

    factor(x)

    [1] Yes No No Yes Yes Levels: No Yes

    table(x)
    x No Yes 2 3
  • 在這個例子中,x是字串資料,而factor()這個函數把x轉換為因素,有No, Yes兩類別。
  • 常用的指令是\(\texttt{table()}\),用途為統計向量的分佈。
  • 因素的優點是容易理解,例如在交叉分析時,屬性為因素的變數可以直接顯示變數的變量:
  • library(car)
    kableExtra::kable_styling(knitr::kable(table(Chile$sex, Chile$vote)))
    A N U Y
    F 104 363 362 480
    M 83 526 226 388
  • 不論是字串或者是因素,比較容易讓人理解交叉分析的結果。例如我們的資料用數字代表地區:
  • Chile$ncode<-as.numeric(Chile$region) 
    kableExtra::kable_styling(knitr::kable(table(Chile$ncode, Chile$vote)))
    A N U Y
    44 210 141 174
    2 18 23 38
    30 102 46 135
    42 214 148 275
    69 345 230 246
  • 或者是繪圖,都可以看出字串的優點。例如圖 2.3 顯示性別與投票的關係:
  • library(lattice)
    plot(Chile$sex, Chile$vote, xlab="Sex", ylab="Vote")
    性別與投票之一

    Figure 2.3: 性別與投票之一

    2.3.1 因素轉換

  • 有時候我們需要把因素轉換成數值,例如教育程度從國小、國中、…轉換成1到6的尺度。或者性別從男、女轉換成0與1。可用\(\texttt{as.numeric()}\)函式,如表??
  • gender<-as.numeric(Chile$sex) 
    kableExtra::kable_styling(knitr::kable(table(gender)))
    gender Freq
    1 1379
    2 1321
  • 可以看到R按照類別的字母順序轉換類別為數字。如果進一步要轉換數字就容易了:
  • sex <- c()
    sex[gender==2]<-0
    sex[gender==1]<-1
    kableExtra::kable_styling(knitr::kable(table(sex)))
    sex Freq
    0 1321
    1 1379
  • 也可以寫語法直接轉換因素為需要的數字:
  • ngender<-c()
    ngender[Chile$sex=='F']<-1
    ngender[Chile$sex=='M']<-0
    kableExtra::kable_styling(knitr::kable(table(ngender)))
    ngender Freq
    0 1321
    1 1379
  • 或是把因素轉換為字串:
  • Chile$gender[Chile$sex=="F"]<-"Female"
    Chile$gender[Chile$sex=="M"]<-"Male"
    class(Chile$gender)

    [1] “character”

    kableExtra::kable_styling(knitr::kable(table(Chile$gender)))
    Var1 Freq
    Female 1379
    Male 1321
  • 如果是字串,可以進行交叉分析,或是畫圖,例如圖 2.4顯示男女投票對象的差異:
  • A N U Y
    Female 104 363 362 480
    Male 83 526 226 388
    性別與投票之二

    Figure 2.4: 性別與投票之二

  • 需要注意字串無法轉換為數字,因為R無法判斷哪一個字串應該被給予哪一個數字。
  • as.numeric(Chile$gender)

    請嘗試練習AMSsurveycitizen等類別變數的轉換。

  • 在上面的範例中:
    1. dplyr套件提供mutate_if這個函式,可以把資料中的所有字串變數一次改成數字或者字串:
    2. dplyr套件提供mutate_at這個函式,可以把資料中的特定變數改成數字或者字串,例如我們想把pscl套件中的year這個變數從數字改成因素,讓之後在視覺化的過程中不會被當成連續數字:
    3. Var1 Freq
      82 3
      84 4
      86 3
      88 4
      90 3
      92 4
      93 1

    2.3.1.1 因素的順序

  • 我們有時候會想指定因素變數的變量的順序,而不是按照電腦自動排列。請輸入:
  • x<-c("花蓮縣","臺北市","屏東縣","臺南市","高雄市");x
    table(x)
  • x的排列方式為“花蓮縣”,“臺北市”,“屏東縣”,“臺南市”,“高雄市”,而分布的排列方式也是如此。
  • 如果希望按照由北到南再到東排列觀察值,可以加上level指令 \(\texttt{xf<-factor(x, levels=c("臺北市", "臺南市","高雄市","屏東縣","花蓮縣"))}\)
  • [1] Levels: 臺北市 臺南市 高雄市 屏東縣 花蓮縣
    xf Freq
    臺北市 0
    臺南市 0
    高雄市 0
    屏東縣 0
    花蓮縣 0
  • 附帶一提,factor()這個函數裡面有ordered的邏輯選項,不過只要指定levels,有無ordered為真並不影響。但是ordered()這個函式會得到一個已經排序的因素,例如:
  • od<-ordered(1:20); class(od)

    [1] “ordered” “factor”

    2.4 邏輯(logic)

  • 資料可以是真(True)或是偽(False)的邏輯,對於篩選資料特別有用。例如我們先建立一筆資料以及邏輯:
  • a<-c(0:9); a

    [1] 0 1 2 3 4 5 6 7 8 9

    ok<-a>5; ok
    [1] FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE
  • 然後用這個邏輯篩選資料:
  • a[ok]

    [1] 6 7 8 9

    請執行以下語法,並且回答篩選後的變數剩下幾個觀察值?

    head(Duncan)
    ok<-Duncan$income>50  
    Duncan$income[ok]
  • 附帶介紹一個指令\(\texttt{length()}\),用途為顯示向量的長度。
  • 有時候我們的資料裡面有遺漏值NA。可以用邏輯加上\(\texttt{is.na()}\)函式,剔除這些遺漏值。例如:
  • library(data.table)
    H<-data.table(Age=c(NA,"30-39","40-49","20-29",
                    "20-29","60-69","60-69","30-39","60-69",
                    "30-39","20-29","20-29","30-39","40-49",
                   "40-49", "40-49","50-59","50-59","20-29",NA), 
                  Vote=c("Ding", NA, "Ko", "Ko", "Ko", 
                         "Ding","Ding",NA,NA, "Ko","Yao","Yao", "Yao","Ding","Ko","Ko","Yao","Yao","Ding","Ko"),
                  pride=c(3,NA, 7, 3, NA, 5, 5, 4, 
                          NA,2,5, 1,6,8, 7, 6, 1, 3,3,5))
  • 如果我們想知道受訪者平均的城市光榮感(pride)有多高,我們應該先剔除遺漏值,計算剩下受訪者的平均值,不然會得到NA:
  • ok Freq
    FALSE 3
    TRUE 17

    [1] NA [1] 4.353

  • 上述的例子是如果沒有回答pride,如果我們想顯示H資料中年齡與投票之間的關係,有無設定邏輯去掉遺漏值會造成影響嗎?

    Ding Ko Yao
    20-29 1 2 2
    30-39 0 1 1
    40-49 1 3 0
    50-59 0 0 2
    60-69 2 0 0
    Ding Ko Yao
    20-29 1 2 2
    30-39 0 1 1
    40-49 1 3 0
    50-59 0 0 2
    60-69 2 0 0
  • 可以發現去掉遺漏值並不會影響交叉列表的結果,也就是R會自動去掉無法列表的遺漏值。但是我們交叉其他變數,就會發現差異。
  • 2.5 日期(date)

  • 請輸入 \(\texttt{Sys.Date()}\)即可顯示今天的日期。日期是一種變數。 as.Date()可以將字串轉變為日期資料。
  • v<-c("2/27/2018", "6/26/2018", "12/31/2018"); class(v)

    [1] “character”

    v.date<-as.Date(v, format='%m/%d/%Y'); class(v.date)

    [1] “Date”

    或者是

    v<-c("", "6/26/2018", "12/31/2018")
    as.Date(v, format='%m/%d/%Y')
    [1] NA “2018-06-26” “2018-12-31”
  • format()則轉換屬性為日期的資料為不同格式,例如:
  • today <- Sys.Date()
    format(today, format='%m/%d/%Y')

    [1] “03/19/2021”

    2.5.1 日期的格式

  • 日期的格式如下:
  • 符號 意義 例子
    %d 01-31
    %a 星期幾的縮寫 Mon
    %A 星期幾 Monday
    %m 月份(數字) 01-12
    %b 月份的縮寫 Jan
    %B 月份的完整寫法 January
    %y 兩位數年份 18
    %Y 年份 2018
  • 我們用format()這個函式轉換已經是日期格式的資料,例如:
  • Today<-Sys.Date(); Today

    [1] “2021-03-19”

    today_format1<-format(Today, format='%Y-%b-%d'); today_format1

    [1] “2021- 3-19”

    today_format2<-format(Today, format='%b/%d/%y'); today_format2

    [1] " 3/19/21"

    today_format3<-format(Today, format='%Y年%b月%d日(%a)'); today_format3

    [1] “2021年 3月19日(五)”

    2.5.2 日期的差距

  • 請輸入:
  • xi<-"1953-06-15" #Xi's birthday
    tsai<-"1956-08-31" #Tsai's birthday
  • 我們可以轉換字串為日期變數,然後計算兩個日期之間的差距:
  • as.Date(c(xi,tsai), origin="1904-01-01")

    [1] “1953-06-15” “1956-08-31”

    difftime(tsai, xi)
    Time difference of 1173 days
  • 在這個例子中,origin指令可設定也可不設定。但是計算某一個數字代表的日期時必須要有起始日:
  • as.Date(1100, origin="2018-08-01")

    [1] “2021-08-05”

    介紹完資料型態之後,接下來介紹資料結構。


    3 資料結構

    3.1 一維

    3.1.1 向量(vector)

  • 向量是最常見的資料結構,可以寫成:
  • example<-c(0,1,2,3,4)
    print(example)

    [1] 0 1 2 3 4

    或者是

    c(2,4,6,8)->A
  • 英文字母的向量:
  • c(letters)

    [1] “a” “b” “c” “d” “e” “f” “g” “h” “i” “j” “k” “l” “m” “n” “o” “p” “q” “r” “s” [20] “t” “u” “v” “w” “x” “y” “z”

    c(LETTERS)
    [1] “A” “B” “C” “D” “E” “F” “G” “H” “I” “J” “K” “L” “M” “N” “O” “P” “Q” “R” “S” [20] “T” “U” “V” “W” “X” “Y” “Z”
  • 有時候我們為向量中的元素加上名稱,方便繪圖,例如在圖 3.1,有兩個向量分別表示某位投資者的資金配置以及2016到2019的現金數量:
  • shares <- c(150, 40,  65)
    names(shares) <- c('Finance','Techonolgy','Cash')
    shares

    Finance Techonolgy Cash 150 40 65

    class(shares)

    [1] “numeric”

    cash<-c(100, 120, 80, 65)
    names(cash) <- c(2016, 2017, 2018, 2019)
    par(mfrow=c(1,2), bg='lightgreen',mai=c(0.4,0.3,0.1,0.3))
    pie(shares); barplot(cash, cex.axis = 0.8)
    資金配置

    Figure 3.1: 資金配置

  • 可以在向量內進行數學運算,例如:
  • j<-c(2*2, 2*9, 10-2, 3^3); j
    [1] 4 18 8 27
  • 向量可以加、減、乘、除其他數字:
  • R<-c(100, 200, 300); R/5; sqrt(R)
    [1] 20 40 60 [1] 10.00 14.14 17.32
  • 一個向量可以合併另一個向量:
  • c(j, R)
    [1] 4 18 8 27 100 200 300
  • 或者是一個向量包含其他向量:
  • Y<-c(j, c(9:5), R[c(1,2)]); Y
    [1] 4 18 8 27 9 8 7 6 5 100 200
  • 因為R的向量可以連結,我們可以增加資料的數量。
  • 用減號可以去除向量中的元素,例如:
  • Y[-c(8:12)]

    [1] 4 18 8 27 9 8 7

    3.2 二維

    3.2.1 矩陣 (matrix)

  • R的資料結構之一是矩陣,例如VADeaths就是一筆矩陣的資料:
  • data("VADeaths"); VADeaths
    ##       Rural Male Rural Female Urban Male Urban Female
    ## 50-54       11.7          8.7       15.4          8.4
    ## 55-59       18.1         11.7       24.3         13.6
    ## 60-64       26.9         20.3       37.0         19.3
    ## 65-69       41.0         30.9       54.6         35.1
    ## 70-74       66.0         54.3       71.1         50.0
    class(VADeaths)
    ## [1] "matrix" "array"
  • 數學的矩陣與R的矩陣類似。矩陣的讀法是先列再行。例如我們需要一個\(3\times 3\)的矩陣可寫成:
  • m<-matrix(c(1:9), nrow=3, ncol=3); m
    ##      [,1] [,2] [,3]
    ## [1,]    1    4    7
    ## [2,]    2    5    8
    ## [3,]    3    6    9
  • 再寫一個\(3\times 2\)矩陣:
  • n<-matrix(c(1:6), nrow=3, ncol=2);n
    ##      [,1] [,2]
    ## [1,]    1    4
    ## [2,]    2    5
    ## [3,]    3    6
  • 兩個矩陣相乘可寫成:
  • m<-matrix(c(1:9), nrow=3, ncol=3); n<-matrix(c(1:6), nrow=3, ncol=2); m%*%n
    ##      [,1] [,2]
    ## [1,]   30   66
    ## [2,]   36   81
    ## [3,]   42   96
  • 矩陣的乘法需要第一個矩陣的行(column)等於第二個矩陣的列(row)。
  • 矩陣的對角向量為:
  • diag(m)
    ## [1] 1 5 9
  • 轉置矩陣為:
  • t(m)
    ##      [,1] [,2] [,3]
    ## [1,]    1    2    3
    ## [2,]    4    5    6
    ## [3,]    7    8    9
  • 如果要替代或者是選取部分的矩陣資料,例如要選取m矩陣的第二列第三行的資料,並且命它為0:
  • m[2,3]; m[2,3]<-0
    ## [1] 8
  • 請嘗試(1)轉置n矩陣(2)輸入以下指令:
  • n<-matrix(c(1:6), nrow=3, ncol=2, byrow=T)
  • 矩陣的列與行命名方式為用dimnames的指令分別對列與行指定名稱,例如:
  • n<-matrix(c(1:6), nrow=3, ncol=2, dimnames = list(c("a","b","c"),c("A","B"))); n
    ##   A B
    ## a 1 4
    ## b 2 5
    ## c 3 6

    3.2.2 資料框 (data frame)

  • 資料框是向量組合起來成為一個類似矩陣的資料,然後指定變數名稱。例如:
  • R1<-c(170, 175, 166, 172, 165, 157, 167, 167, 
            156, 160)
    R2<-c("F","M","M","M","F","F","F","F","M","F")
    R3<-R1/10 + 42
    R123<-data.frame(height=R1,gender=R2,weight=R3, 
                     stringsAsFactors = FALSE)
    R123
    ##    height gender weight
    ## 1     170      F   59.0
    ## 2     175      M   59.5
    ## 3     166      M   58.6
    ## 4     172      M   59.2
    ## 5     165      F   58.5
    ## 6     157      F   57.7
    ## 7     167      F   58.7
    ## 8     167      F   58.7
    ## 9     156      M   57.6
    ## 10    160      F   58.0
  • 資料框的每一行必須有相同的長度,每一列也必須要有同樣數目的數字、文字等。
  • 如果沒有特別指定資料框,R會當做矩陣。例如:
  • H<-cbind(LETTERS[1:6], seq(10,60, 10))
    H
    ##      [,1] [,2]
    ## [1,] "A"  "10"
    ## [2,] "B"  "20"
    ## [3,] "C"  "30"
    ## [4,] "D"  "40"
    ## [5,] "E"  "50"
    ## [6,] "F"  "60"
    class(H)
    ## [1] "matrix" "array"

    3.2.3 Matrix 或 dataframe?

    1. 資料框允許不同性質的變數,但是矩陣只接受同一類型的變數。
    2. ggplot2 畫圖時只能使用資料框。
    3. 雖然矩陣容許欄位名稱,但是只能用matrix[,1]告訴系統向量位置, 不能用matrix$a。
    4. 矩陣無法設定\(\texttt{stringAsFactor=F}\),資料框才可以。
  • 我們創造兩個簡單的變數,構成矩陣:
  • ## [1] "matrix" "array"
    ##      a           b     
    ## [1,] "Monday"    "52.5"
    ## [2,] "Tuesday"   "48.4"
    ## [3,] "Wednesday" "57.1"
    ## [4,] "Thursday"  "60.1"
    ## [5,] "Friday"    "71.1"
  • 如果執行上面區塊中的ggplot2語法,會出現錯誤訊息。但是矩陣還是可以畫圖,我們用Chile資料的投票與性別為例如圖??
  • tm<-cbind(carData::Chile$vote, carData::Chile$sex)
    class(tm)

    [1] “matrix” “array”

    plot(table(tm[,2], tm[,1]))
  • 在上面星期一到五的例子,我們改成資料框,即可畫圖3.2表示每一天的快樂程度:
  • dt <- as.data.frame(dftest)
    dt$a<-factor(dt$a, levels=c("Monday", "Tuesday", 
                "Wednesday", "Thursday", "Friday"))
    ggplot(data=dt, aes(x=a, y=b, fill=a)) +
       geom_bar(stat = 'identity')
    週一至週五的快樂程度

    Figure 3.2: 週一至週五的快樂程度

    有幾個資料框與矩陣的相關指令:

    • nrow(x):顯示x資料框或矩陣的列數量,也等於是觀察值數目
    • ncol(x):顯示x資料框或矩陣的行數量,也等於是變數數目
    • dim(x):同時顯示x資料框或矩陣的行列的數量
    • str(x):顯示x資料框或矩陣的性質以及變數名稱與性質
    • head(x):顯示x資料框或矩陣的前6列
    • head(x, n=a):顯示x資料框或矩陣的前a列
    • colnames(x):顯示或設定x資料框或矩陣的變數或欄位名稱
    • rownames(x):顯示或設定x資料框或矩陣每一列的名稱
    • 有關rownames的更多說明,請參考這個部落格
    • 例如我們想知道AMSsurvey有幾筆觀察值:
    nrow(AMSsurvey)
    [1] 24
  • 如果想要改變欄位名稱,可以這麼做:
  • colnames(R123)<-c("v1","v2","v3"); R123
    ##     v1 v2   v3
    ## 1  170  F 59.0
    ## 2  175  M 59.5
    ## 3  166  M 58.6
    ## 4  172  M 59.2
    ## 5  165  F 58.5
    ## 6  157  F 57.7
    ## 7  167  F 58.7
    ## 8  167  F 58.7
    ## 9  156  M 57.6
    ## 10 160  F 58.0
  • 有的資料框的最左邊是流水號,有的資料框沒有,前者可能是因為從csv等工作表讀取而來,被賦予流水號,但是並不是第一行,真正的第一行應該有欄位的名稱。有的資料框則用字串當做列的名稱:
  • library(ISLR)
    head(College, n=3)
    ##                              Private Apps Accept Enroll Top10perc Top25perc
    ## Abilene Christian University     Yes 1660   1232    721        23        52
    ## Adelphi University               Yes 2186   1924    512        16        29
    ## Adrian College                   Yes 1428   1097    336        22        50
    ##                              F.Undergrad P.Undergrad Outstate Room.Board Books
    ## Abilene Christian University        2885         537     7440       3300   450
    ## Adelphi University                  2683        1227    12280       6450   750
    ## Adrian College                      1036          99    11250       3750   400
    ##                              Personal PhD Terminal S.F.Ratio perc.alumni Expend
    ## Abilene Christian University     2200  70       78      18.1          12   7041
    ## Adelphi University               1500  29       30      12.2          16  10527
    ## Adrian College                   1165  53       66      12.9          30   8735
    ##                              Grad.Rate
    ## Abilene Christian University        60
    ## Adelphi University                  56
    ## Adrian College                      54
  • rownames 可以幫助我們刪掉不需要的資料。例如我們有一筆美國各州的資料:
  • head(state.x77, n=5)
    ##            Population Income Illiteracy Life Exp Murder HS Grad Frost   Area
    ## Alabama          3615   3624        2.1    69.05   15.1    41.3    20  50708
    ## Alaska            365   6315        1.5    69.31   11.3    66.7   152 566432
    ## Arizona          2212   4530        1.8    70.55    7.8    58.1    15 113417
    ## Arkansas         2110   3378        1.9    70.66   10.1    39.9    65  51945
    ## California      21198   5114        1.1    71.71   10.3    62.6    20 156361
  • 我們想刪掉Alabama, Alaska, Arkansas三個州的資料,先成立一個矩陣:
  • names.to.delete<-c('Alabama', 'Alaska', 'Arkansas')
  • 再用which(rownames(data) %in% vector)傳回所要選出的列:
  • rows.to.delete<-which(rownames(state.x77) %in% names.to.delete) 
  • 最後用\(\texttt{data[-c(), ]}\)刪掉所選的列:
  • newstate <- state.x77[-c(rows.to.delete),]
    head(newstate, n=5)
    ##             Population Income Illiteracy Life Exp Murder HS Grad Frost   Area
    ## Arizona           2212   4530        1.8    70.55    7.8    58.1    15 113417
    ## California       21198   5114        1.1    71.71   10.3    62.6    20 156361
    ## Colorado          2541   4884        0.7    72.06    6.8    63.9   166 103766
    ## Connecticut       3100   5348        1.1    72.48    3.1    56.0   139   4862
    ## Delaware           579   4809        0.9    70.06    6.2    54.6   103   1982
  • 更進一步的篩選資料方法將會在後面課程介紹。

  • 3.3 多維

    3.3.1 陣列 (array)

  • 陣列容納一個以上的矩陣,只有一個矩陣的陣列相當於矩陣:
  • Array1 <- array(1:12, dim = c(2, 6, 1)); Array1
    ## , , 1
    ## 
    ##      [,1] [,2] [,3] [,4] [,5] [,6]
    ## [1,]    1    3    5    7    9   11
    ## [2,]    2    4    6    8   10   12
  • 而有多個矩陣的陣列如:
  • Array2 <- array(1:12, dim = c(2, 3, 2)); Array2
    ## , , 1
    ## 
    ##      [,1] [,2] [,3]
    ## [1,]    1    3    5
    ## [2,]    2    4    6
    ## 
    ## , , 2
    ## 
    ##      [,1] [,2] [,3]
    ## [1,]    7    9   11
    ## [2,]    8   10   12
  • 陣列的優點是同時容納一個以上的矩陣,如果只需要某一個矩陣,可以這樣取出:
  • A12<-Array2[,,2]; A12
    ##      [,1] [,2] [,3]
    ## [1,]    7    9   11
    ## [2,]    8   10   12

    3.3.2 列表 (list)

  • 列表的特性為資料的長度、結構沒有限制,例如:
  • listA<-list(R123, H, c(xi,tsai)); listA
    ## [[1]]
    ##     v1 v2   v3
    ## 1  170  F 59.0
    ## 2  175  M 59.5
    ## 3  166  M 58.6
    ## 4  172  M 59.2
    ## 5  165  F 58.5
    ## 6  157  F 57.7
    ## 7  167  F 58.7
    ## 8  167  F 58.7
    ## 9  156  M 57.6
    ## 10 160  F 58.0
    ## 
    ## [[2]]
    ##      [,1] [,2]
    ## [1,] "A"  "10"
    ## [2,] "B"  "20"
    ## [3,] "C"  "30"
    ## [4,] "D"  "40"
    ## [5,] "E"  "50"
    ## [6,] "F"  "60"
    ## 
    ## [[3]]
    ## [1] "1953-06-15" "1956-08-31"
  • 又例如我們在一個列表中,創造兩個資料框並給定名稱:
  • list(A=data.frame(x=c(1:5),y=c(101:105)), 
         B=data.frame(v1=rep(NA,6)))
    ## $A
    ##   x   y
    ## 1 1 101
    ## 2 2 102
    ## 3 3 103
    ## 4 4 104
    ## 5 5 105
    ## 
    ## $B
    ##   v1
    ## 1 NA
    ## 2 NA
    ## 3 NA
    ## 4 NA
    ## 5 NA
    ## 6 NA
  • 如果要取出列表中的某一個部分資料,可以寫成:
  • listA[[3]]
    ## [1] "1953-06-15" "1956-08-31"
  • 列表的優點是儲存尚未格式化的資料,但是資料相當龐大,矩陣與陣列的資料分散為一個個元素,不容易取出,如果事先命名,就比較容易了解哪些元素來自於什麼資料。例如:
  • listB<-list(data=R123, vec=m, char=c(tsai, xi)); 
    listB[["data"]]
    ##     v1 v2   v3
    ## 1  170  F 59.0
    ## 2  175  M 59.5
    ## 3  166  M 58.6
    ## 4  172  M 59.2
    ## 5  165  F 58.5
    ## 6  157  F 57.7
    ## 7  167  F 58.7
    ## 8  167  F 58.7
    ## 9  156  M 57.6
    ## 10 160  F 58.0
  • 如果列表中的變數有同樣的長度,可以用\(\texttt{setDT()}\)轉換列表為data.table。例如:
  • X = list(1:5, letters[1:5], c('Y','Y','N','Y','N'),
             c("2/27/2018", "6/26/2018", "12/31/2018","1/20/2019","4/8/2019")); X
    ## [[1]]
    ## [1] 1 2 3 4 5
    ## 
    ## [[2]]
    ## [1] "a" "b" "c" "d" "e"
    ## 
    ## [[3]]
    ## [1] "Y" "Y" "N" "Y" "N"
    ## 
    ## [[4]]
    ## [1] "2/27/2018"  "6/26/2018"  "12/31/2018" "1/20/2019"  "4/8/2019"
    X.dt<-setDT(X); X.dt
    ##    V1 V2 V3         V4
    ## 1:  1  a  Y  2/27/2018
    ## 2:  2  b  Y  6/26/2018
    ## 3:  3  c  N 12/31/2018
    ## 4:  4  d  Y  1/20/2019
    ## 5:  5  e  N   4/8/2019
    請嘗試把c('a','b','c'), c(1,2,3,4)以及
    c('2018-01-01', '2018-04-04', '2018-04-05', '2018-06-18', '2018-10-10')`結合成為一個列表。  

    3.3.3 表格 (table)

  • Titanic這筆資料為表格的型態,同時也是四個陣列,
  • class(Titanic); Titanic
    ## [1] "table"
    ## , , Age = Child, Survived = No
    ## 
    ##       Sex
    ## Class  Male Female
    ##   1st     0      0
    ##   2nd     0      0
    ##   3rd    35     17
    ##   Crew    0      0
    ## 
    ## , , Age = Adult, Survived = No
    ## 
    ##       Sex
    ## Class  Male Female
    ##   1st   118      4
    ##   2nd   154     13
    ##   3rd   387     89
    ##   Crew  670      3
    ## 
    ## , , Age = Child, Survived = Yes
    ## 
    ##       Sex
    ## Class  Male Female
    ##   1st     5      1
    ##   2nd    11     13
    ##   3rd    13     14
    ##   Crew    0      0
    ## 
    ## , , Age = Adult, Survived = Yes
    ## 
    ##       Sex
    ## Class  Male Female
    ##   1st    57    140
    ##   2nd    14     80
    ##   3rd    75     76
    ##   Crew  192     20
  • 可以看到這筆資料有四個變數:艙等、性別、年齡、是否存活。 因為有四個陣列,所以我們取出其中一個表格時需要給定兩個條件,如果設定三個條件,就是一個向量,如果設定四個就是一個元素。 例如我們想知道沒有生還的兒童搭的艙等與性別,也就是第一個表格,可以這樣輸入:
  • T1<-Titanic[, , 1, 1]
    class(T1); T1
    ## [1] "table"
    ##       Sex
    ## Class  Male Female
    ##   1st     0      0
    ##   2nd     0      0
    ##   3rd    35     17
    ##   Crew    0      0
  • 顯示沒有生還的兒童都是搭三等艙,男童為女童一倍。如果我們想知道艙等與生還的關係,可以先試著呈現:
  • Titanic[, 1, 1,]
    ##       Survived
    ## Class  No Yes
    ##   1st   0   5
    ##   2nd   0  11
    ##   3rd  35  13
    ##   Crew  0   0
    Titanic[, 1, 2,]
    ##       Survived
    ## Class   No Yes
    ##   1st  118  57
    ##   2nd  154  14
    ##   3rd  387  75
    ##   Crew 670 192
    Titanic[, 2, 1,]
    ##       Survived
    ## Class  No Yes
    ##   1st   0   1
    ##   2nd   0  13
    ##   3rd  17  14
    ##   Crew  0   0
    Titanic[, 2, 2,]
    ##       Survived
    ## Class   No Yes
    ##   1st    4 140
    ##   2nd   13  80
    ##   3rd   89  76
    ##   Crew   3  20

    3.3.4 資料表

  • 資料表(data.table)是資料框的延伸,可以直接在資料中計算特定的列或是行。例如:
  • library(data.table)
    DT = data.table(a = 1:3, b = c(10,20,30))
    DT
    ##    a  b
    ## 1: 1 10
    ## 2: 2 20
    ## 3: 3 30
    DT[1:3, sum(a)]
    ## [1] 6
    DT[1:2, mean(b)]
    ## [1] 15
  • 在創造一個資料表之後,先計算a變數的總和,然後算b變數前兩個值的平均。
  • 也可以直接繪圖,例如我們先建立一個常態分佈的變數在圖 ,然後畫出機率密度圖3.3
  • DT <-data.table(x=rnorm(1000, 0, 1))
    DT[, plot(density(x), type='l', xlab='x', ylab='',
              lwd=3, col='lightblue')]
    常態分佈機率密度

    Figure 3.3: 常態分佈機率密度

    NULL

  • 資料表的功能非常多,相較於資料框來得複雜,不過這門課程主要用資料框來處理資料。對於資料表有興趣的同學可以參考該套件的網站
  • 3.4 小結

  • 資料框在各種資料結構之中,是最常被用到的。如果要把資料提出,最好把各種資料結構轉成資料框。例如我們想知道一筆資料的變數性質:
  • g<-Titanic[ , , 2, 2]; class(g)
    ## [1] "table"

    請輸入 \(\texttt{g\$Class}\)結果發生錯誤,無法顯示。改為:

    g<-data.frame(g)

    請輸入 \(\texttt{g\$Class}\)則會顯示變數的性質。

    4 基本運算

    4.1 向量的運算

    因為向量具有方位的性質,所以數字具有先後順序,與另一個有同樣數目的向量相加減乘除時,將會依照順序進行運算。我們以一個純量 (scalar) Sca 為例:

    X<-c(10,20,30,40,50,60); Sca<-10
    X+Sca
    [1] 20 30 40 50 60 70
  • 如果是乘或是除,就是每個元素同時乘或除某個數:
  • X/Sca
    [1] 1 2 3 4 5 6
  • 如果是乘或是除另一個矩陣向量,就是兩個向量對應的每個元素進行乘或除:
  • Y<-c(5,10,6,8,25,6)
    X/Y; X*Y

    [1] 2 2 5 5 2 10 [1] 50 200 180 320 1250 360

  • 也可以運算平方與開根號:
  • a<-c(2,3,4); b<-a^2; print(b)

    [1] 4 9 16

    c<-sqrt(b); print(c)

    [1] 2 3 4

    4.2 進位

  • 進位的指令有:
    1. round:四捨五入
    2. floor:強制捨去
    3. ceiling:強制進位
  • 我們用以下例子顯示進位的指令功能:
  • a1<-c(2.54, 3.111, 10.999)
    round(a1, digits=2)
    ## [1]  2.54  3.11 11.00
    floor(a1)
    ## [1]  2  3 10
    ceiling(a1)
    ## [1]  3  4 11
  • 也可以在執行指令前,設定小數點前後顯示的數字數目:
  • ## [1]  2.54  3.11 11.00
  • 比較麻煩的是R為了對齊輸出的數字,會輸出比較多的小數點後面的數字,可以考慮用sprintf這個函式控制,但是會得到字串而非數字:
  • ## [1] 6.00 0.91 3.29
    ## [1] "6.00" "0.91" "3.29"

    5 資料型態作業

    1. 使用orange資料,把Tree變數換成A, B, C, D, E,然後顯示每一個類型的數量。 2. 請用weekdays()指令顯示今天上課日期是星期二。

    3. 請問在mtcars資料裡面,wt大於或等於2的資料有幾筆?

    4. 請嘗試建立一個包含流水號序號、一個數字變數、一個類別變數的資料框或資料表。

    5. 請創造一個對角向量為{0,0,0}的矩陣。

    6. 請用data.table計算Titanic男性與女性生還的人數。

    7. 請問faithful這筆資料有多少個觀察值?

    8. 請建立三個\(3\times 2\)的陣列。

    9. 請把Arrests資料裡面的employed變數改成0, 1

    10. 請用三種格式表示今天的日期。

    6 基本運算作業

    1. 請用程式計算 \(\text{log}(\frac{14}{5})=\)?

    2. 請用程式計算 \(1\times 2\times 3\times , \dots ,\times 8=\)?

    3. 用程式計算英文有幾個字母。

    4. 請以程式顯示在您寫作業的這一天,今年已經過了幾天?

    5. 請寫一段語法把今天的氣溫轉換成華氏。

    6. 小傑的祖父是民國35年出生, 祖母36年出生,父親53年次,母親60年次, 他自己27歲,他妹妹23歲。請問小傑家的平均年齡幾歲?最年長跟最年輕差幾歲?總和幾歲?

    7. 續上題,請問小傑家的3名女性平均幾歲?3名男性平均幾歲?

    8. 續上題,如果小傑結婚,他的太太是26歲,小傑家多一個成員,請問婚後小傑家的女性平均幾歲?

    9. 請建立一個資料框,列出彩虹七種顏色的中、英文。然後按照英文遞增的順序,排列整個資料框。

    10. 續上題,請用data.table這個套件的功能,排序上述的資料框。

    7 更新日期

    最後更新日期 03/19/2021