Data Frame and Matrix

主要參考資料

  • 曾意儒, Chapter 2.5

  • RDS: Chapter 11 Data import

  • Matrix (矩陣)- A matrix is a collection of data elements arranged in a two-dimensional rectangular layout (方/長方形排列).

  • DataFrame - A dataframe is used for storing data tables. It is a list of vectors of equal length.

Matrix

Matrix:

Mat1 <- matrix(
  c(1:6), 2,3
)
Mat1
##      [,1] [,2] [,3]
## [1,]    1    3    5
## [2,]    2    4    6

Matrix只是vector的一種新的排列形式,雖然它的class自成一格為matrix,但它的type依然會是它架構根源的atomic vector形式。

class(Mat1)
## [1] "matrix"
typeof(Mat1)
## [1] "integer"
Mat2 <- matrix(
  c("a","b","c","d"), 2, 2
)
Mat2
##      [,1] [,2]
## [1,] "a"  "c" 
## [2,] "b"  "d"

注意:Matrix是以atomic vector為基礎的一種排列形式,所以它的元素type一定齊質。

Data Frame

考慮以下資料,它含有學號,姓名,成績等三個資料變數,變數裡的元素個別代表一筆資料:

list:因為三個變數向量的type不相同,只能用list儲存。

StuList <- list(
  學號=c(172,214,322,425,517),
  姓名=c("小明","大雄","胖虎","小新","大白"),
  成績=c(80,60,90,70,50)
  )
StuList 
## $學號
## [1] 172 214 322 425 517
## 
## $姓名
## [1] "小明" "大雄" "胖虎" "小新" "大白"
## 
## $成績
## [1] 80 60 90 70 50

data frame:若每個變數相同元素位置來自於同一筆資料,我們可以使用data frame的class來儲存這樣的(長)方形資料表。

StuDF <- data.frame(
  學號=c(172,214,322,425,517),
  姓名=c("小明","大雄","胖虎","小新","大白"),
  成績=c(80,60,90,70,50)
  )
StuDF 
##   學號 姓名 成績
## 1  172 小明   80
## 2  214 大雄   60
## 3  322 胖虎   90
## 4  425 小新   70
## 5  517 大白   50

data.frame()遇到變數輸入為character class時,內定會被轉成factor。

class(StuDF$姓名)
## [1] "factor"
StuDF$姓名 <- as.character(StuDF$姓名)
class(StuDF$姓名)
## [1] "character"

取消內定character為factor的方式:as.data.frame(..., stringsAsFactors = FALSE)

class(StuList)
## [1] "list"
as.data.frame(StuList) -> StuDF3

class(StuDF3)
## [1] "data.frame"
StuDF3
##   學號 姓名 成績
## 1  172 小明   80
## 2  214 大雄   60
## 3  322 胖虎   90
## 4  425 小新   70
## 5  517 大白   50
as.data.frame(StuList,stringsAsFactors = F) -> StuDF4
class(StuDF4)
## [1] "data.frame"
StuDF4
##   學號 姓名 成績
## 1  172 小明   80
## 2  214 大雄   60
## 3  322 胖虎   90
## 4  425 小新   70
## 5  517 大白   50

data.frame(..., stringsAsFactors = FALSE)

StuDF2 <- data.frame(
  學號=c(172,214,322,425,517),
  姓名=c("小明","大雄","胖虎","小新","大白"),
  成績=c(80,60,90,70,50),
  stringsAsFactors = FALSE
  )
StuDF2 
##   學號 姓名 成績
## 1  172 小明   80
## 2  214 大雄   60
## 3  322 胖虎   90
## 4  425 小新   70
## 5  517 大白   50

Data frame其本質(即type)是list vector,但因它的資料表配置特性而會有更豐富的特質,因此其class會自成一類。

class(StuDF)
## [1] "data.frame"
typeof(StuDF)
## [1] "list"

data frame的建立也可以用list去建好,再透過as.data.frame()去改變其class成data frame.

[.R , .C] object extraction

[.R,.C]: 為方形資料class(即matrix和data frame),獨有的object extraction。

  • 只有一個[]中括號,所以和[.].有相同的規則: .R.C可以用

    • 數值向量:如c(1,8,12)

    • 邏輯向量:如c(T,T,F)

    • 元素名稱向量(當元素有名字時)

  • .R: 代表哪幾列(rows); .C: 代表哪幾欄/行(columns)

LETTERS # R內設元素值為英文字母群的character vector
##  [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q"
## [18] "R" "S" "T" "U" "V" "W" "X" "Y" "Z"
chosenLETTERS <- LETTERS[1:15]
matObj1 <- matrix(chosenLETTERS,5,3)
matObj1
##      [,1] [,2] [,3]
## [1,] "A"  "F"  "K" 
## [2,] "B"  "G"  "L" 
## [3,] "C"  "H"  "M" 
## [4,] "D"  "I"  "N" 
## [5,] "E"  "J"  "O"
chosenLETTERS[8]
## [1] "H"
matObj1[8]
## [1] "H"
matObj1
##      [,1] [,2] [,3]
## [1,] "A"  "F"  "K" 
## [2,] "B"  "G"  "L" 
## [3,] "C"  "H"  "M" 
## [4,] "D"  "I"  "N" 
## [5,] "E"  "J"  "O"
matObj1[3,2] 
## [1] "H"
matObj1[c(F,F,TRUE,F,F),c(F,TRUE,F)]
## [1] "H"

若只用[.] extraction, 如何取出matObj1[c(1,5),c(2,3)]的元素值?

StuDF
##   學號 姓名 成績
## 1  172 小明   80
## 2  214 大雄   60
## 3  322 胖虎   90
## 4  425 小新   70
## 5  517 大白   50
StuDF[c("姓名","成績")] 
##   姓名 成績
## 1 小明   80
## 2 大雄   60
## 3 胖虎   90
## 4 小新   70
## 5 大白   50
StuDF[1:5,c("姓名","成績")] 
##   姓名 成績
## 1 小明   80
## 2 大雄   60
## 3 胖虎   90
## 4 小新   70
## 5 大白   50

.R, .C不填寫,則表示「全取」的意思:

StuDF[,c("姓名","成績")]
##   姓名 成績
## 1 小明   80
## 2 大雄   60
## 3 胖虎   90
## 4 小新   70
## 5 大白   50

請出matObj1的第3欄。

matObj1[,3]
## [1] "K" "L" "M" "N" "O"
cbind(matObj1,letters[1:5])
##      [,1] [,2] [,3] [,4]
## [1,] "A"  "F"  "K"  "a" 
## [2,] "B"  "G"  "L"  "b" 
## [3,] "C"  "H"  "M"  "c" 
## [4,] "D"  "I"  "N"  "d" 
## [5,] "E"  "J"  "O"  "e"

請取出StuDF中小新的成績:

StuDF
##   學號 姓名 成績
## 1  172 小明   80
## 2  214 大雄   60
## 3  322 胖虎   90
## 4  425 小新   70
## 5  517 大白   50
StuList
## $學號
## [1] 172 214 322 425 517
## 
## $姓名
## [1] "小明" "大雄" "胖虎" "小新" "大白"
## 
## $成績
## [1] 80 60 90 70 50

若是用StuList,你要怎麼取?

StuDF[4,c("成績")]
## [1] 70

names, colnames, rownames

  • names():

    • vector角度對元素進行名稱查詢

    • names() <-:可用來命名。

Vector1 <- letters[1:6]
Vector1
## [1] "a" "b" "c" "d" "e" "f"
names(Vector1)
## NULL
names(Vector1) <- c('名稱1','名稱2','名稱3','名稱4','名稱5','名稱6')
names(Vector1)
## [1] "名稱1" "名稱2" "名稱3" "名稱4" "名稱5" "名稱6"
Mat1
##      [,1] [,2] [,3]
## [1,]    1    3    5
## [2,]    2    4    6
names(Mat1) 
## NULL
names(Mat1) <- letters[1:6]
names(Mat1)
## [1] "a" "b" "c" "d" "e" "f"

請將StuDF的欄位變數名稱改成StudentID, Name, Grade。

  • colnames()rownames()

    • 分別對方形資料class(即matrix與data frame)的欄(column)及行(row)進行名稱查詢。

    • colnames() <-rownames() <-:可用來命名。

matObj1
##      [,1] [,2] [,3]
## [1,] "A"  "F"  "K" 
## [2,] "B"  "G"  "L" 
## [3,] "C"  "H"  "M" 
## [4,] "D"  "I"  "N" 
## [5,] "E"  "J"  "O"
colnames(matObj1) 
## NULL
rownames(matObj1)
## NULL
colnames(matObj1) <-c('欄位1','欄位2','欄位3')
colnames(matObj1)
## [1] "欄位1" "欄位2" "欄位3"
matObj1
##      欄位1 欄位2 欄位3
## [1,] "A"   "F"   "K"  
## [2,] "B"   "G"   "L"  
## [3,] "C"   "H"   "M"  
## [4,] "D"   "I"   "N"  
## [5,] "E"   "J"   "O"
rownames(matObj1) <- c('行:1','行:2','行:3','行:4','行:5')
matObj1
##       欄位1 欄位2 欄位3
## 行:1 "A"   "F"   "K"  
## 行:2 "B"   "G"   "L"  
## 行:3 "C"   "H"   "M"  
## 行:4 "D"   "I"   "N"  
## 行:5 "E"   "J"   "O"

請使用字串名稱,用[,]取出row 3, 5及column 1,3的值。

Data Frame新增變數

使用[[.]] <-$. <-,其中.為新變數名稱

StuDF
##   學號 姓名 成績
## 1  172 小明   80
## 2  214 大雄   60
## 3  322 胖虎   90
## 4  425 小新   70
## 5  517 大白   50
StuDF[["性別"]] <- c("男","男","男","女","女") 
StuDF
##   學號 姓名 成績 性別
## 1  172 小明   80   男
## 2  214 大雄   60   男
## 3  322 胖虎   90   男
## 4  425 小新   70   女
## 5  517 大白   50   女
StuDF$性別 <- c("男","男","男","女","女") 
StuDF
##   學號 姓名 成績 性別
## 1  172 小明   80   男
## 2  214 大雄   60   男
## 3  322 胖虎   90   男
## 4  425 小新   70   女
## 5  517 大白   50   女

課堂練習

1.

以下各題以課堂調查的classSurvey資料框(data frame)為主:

library(readr)
classSurvey <- read_csv("https://raw.githubusercontent.com/tpemartin/github-data/master/classSurvey.csv")
## Parsed with column specification:
## cols(
##   Timestamp = col_character(),
##   學號 = col_double(),
##   居住地行政區 = col_character(),
##   性別 = col_character(),
##   本學期學分數 = col_double(),
##   本學期目前已參加之課外活動 = col_character()
## )

1.1 使用dim()查詢classSurvey有多少觀察值?有多少變數?(前者也可以用nrow(), 後者也可以用ncol())

1.2 新增一個變數叫年級,它必需是個factor,且有四個levels:大一,大二,大三,大四及以上。(hint: 取出適當的學號碼,透過as.factor(),levels()來達成。)

1.3 各年級有多少人?

1.4 在課堂調查的classSurvey裡大二(含)以上的人有多少比例為男性? (hint: length()可計算vector(如一個變數)有多少元素,dim()計算矩陣或data frame有多少個row(即觀測值個數)及多少個column(即變數數目))

1.5 大一的男性比例又有多少呢?

1.6 學生參加最多的課外活動是什麼?請適當利用table()呈現。

1.7 學生來自的縣市分佈如何?請適當利用table()呈現。