第 7 章 Data Frame and Matrix
7.1 主要參考資料
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.
7.2 Matrix
Matrix:
Mat1 <- matrix(
c(1:6), 2,3
)
Mat1
Matrix只是vector的一種新的排列形式,雖然它的class自成一格為matrix,但它的type依然會是它架構根源的atomic vector形式。
class(Mat1)
typeof(Mat1)
Mat2 <- matrix(
c("a","b","c","d"), 2, 2
)
Mat2
注意:Matrix是以atomic vector為基礎的一種排列形式,所以它的元素type一定齊質。
7.3 Data Frame
考慮以下資料,它含有學號,姓名,成績等三個資料變數,變數裡的元素各別代表一筆資料:
list:因為三個變數向量的type不相同,只能用list儲存。
StuList <- list(
學號=c(172,214,322,425,517),
姓名=c("小明","大雄","胖虎","小新","大白"),
成績=c(80,60,90,70,50)
)
StuList
data frame:若每個變數相同元素位置來自於同一筆資料,我們可以使用data frame的class來儲存這樣的(長)方形資料表。
StuDF <- data.frame(
學號=c(172,214,322,425,517),
姓名=c("小明","大雄","胖虎","小新","大白"),
成績=c(80,60,90,70,50)
)
StuDF
data.frame()
遇到變數輸入為character class時,內定會被轉成factor。
class(StuDF$姓名)
StuDF$姓名 <- as.character(StuDF$姓名)
class(StuDF$姓名)
取消內定character為factor的方式:as.data.frame(..., stringsAsFactors = FALSE)
class(StuList)
as.data.frame(StuList) -> StuDF3
class(StuDF3)
StuDF3
as.data.frame(StuList,stringsAsFactors = F) -> StuDF4
class(StuDF4)
StuDF4
data.frame(..., stringsAsFactors = FALSE)
StuDF2 <- data.frame(
學號=c(172,214,322,425,517),
姓名=c("小明","大雄","胖虎","小新","大白"),
成績=c(80,60,90,70,50),
stringsAsFactors = FALSE
)
StuDF2
Data frame其本質(即type)是list vector,但因它的資料表配置特性而會有更豐富的特質,因此其class會自成一類。
class(StuDF)
typeof(StuDF)
data frame的建立也可以用list去建好,再透過as.data.frame()
去改變其class成data frame.
7.4 [.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
chosenLETTERS <- LETTERS[1:15]
matObj1 <- matrix(chosenLETTERS,5,3)
matObj1
chosenLETTERS[8]
matObj1[8]
matObj1
matObj1[3,2]
matObj1[c(F,F,TRUE,F,F),c(F,TRUE,F)]
若只用[.]
extraction, 如何取出matObj1[c(1,5),c(2,3)]
的元素值?
StuDF
StuDF[c("姓名","成績")]
StuDF[1:5,c("姓名","成績")]
若.R
, .C
不填寫,則表示「全取」的意思:
StuDF[,c("姓名","成績")]
請出matObj1的第3欄。
matObj1[,3]
cbind(matObj1,letters[1:5])
請取出StuDF中小新的成績:
StuDF
StuList
若是用StuList,你要怎麼取?
StuDF[4,c("成績")]
7.5 names, colnames, rownames
names()
:從vector角度對元素進行名稱查詢
names() <-
:可用來命名。
Vector1 <- letters[1:6]
Vector1
names(Vector1)
names(Vector1) <- c('名稱1','名稱2','名稱3','名稱4','名稱5','名稱6')
names(Vector1)
Mat1
names(Mat1)
names(Mat1) <- letters[1:6]
names(Mat1)
請將StuDF的欄位變數名稱改成StudentID, Name, Grade。
colnames()
,rownames()
:分別對方形資料class(即matrix與data frame)的欄(column)及行(row)進行名稱查詢。
colnames() <-
,rownames() <-
:可用來命名。
matObj1
colnames(matObj1)
rownames(matObj1)
colnames(matObj1) <-c('欄位1','欄位2','欄位3')
colnames(matObj1)
matObj1
rownames(matObj1) <- c('行:1','行:2','行:3','行:4','行:5')
matObj1
請使用字串名稱,用[,]
取出row 3, 5及column 1,3的值。
7.6 新增/替換元素
元素提取[.]
,[[.]]
,$.
也可用來進行元素「值」修改或「新增」。
若
.
所指定的元素不存在,則為「新增」。若
.
所指定的元素存在,則為「修改」。
7.6.1 使用[[.]] <-
或$. <-
範例
a <- c("1","b","TRUE")
a
a[[2]] <- "c" # 元素存在
a[[5]] <- "7" # 元素不存在
a
請將下面的TRUE換成FALSE, 並增加第5個元素其值為數字7。
b <- list(
元素1=1,
元素2="Hello",
元素3=TRUE
)
List物件比atomic vector多了使用$.
提取元素的選擇,
唯
.
必需是元素名稱。- 由於data frame也是list type,所以也可以用
$.
來提取/新增/修改變數欄位值。
使用$.
將上一個練習b的第2個元素改成“Hi”,且新增一個名為「新成員」的整數向量其值為整數2,5,1。(「新成員」的class是integer)
引入以下匯率資料:
library(readr)
exData3 <- read_csv("https://raw.githubusercontent.com/tpemartin/github-data/master/exData3.csv",
col_types = cols(
匯率 = col_number(),
期間 = col_character()))
取出「期間」變數轉成date class。
增加一個「isAsiaCrisis」的logical變數,其值為TRUE若「期間」介於1997-06-01到1998-12-01(含前後)。
利用「isAsiaCrisis」值,結合使用
[.R,.C]
取出1997-06-01到1998-12-01亞洲金融危機的子樣本。
7.6.2 使用[.] <-
由於[.]
是一個中括號取法,
- 主要用於增加多個元素。
然而一個中括號會保留母層結構,所以<-
右側要保留母層資料創立方式(即被提取物件的class):
母層若為list,則需用
list(...)
方式增加。母層若為data frame,則需用
data.frame(...)
方式增加。母層若為atomic vector,則用
c(...)
方式增加。
範例
a2 <- c(2,5,10)
a2
a2[c(3,7)] <- c(-1,0)
a2
範例
b2 <- list(
元素1=c(1,4,9),
元素2=c("Hello"),
元素3=c(T,T,F,F,F,T,T)
)
b2
b2[c(2,4)] <- list(
c("Hi","How are you?"),
c(-1,-2)
)
b2
執行以下程序:
StuDF <- data.frame(
學號=c(172,214,322,425,517),
姓名=c("小明","大雄","胖虎","小新","大白"),
成績=c(80,60,90,70,50)
)
將成績各減5分,同時增加一個logical class變數叫「及格」其值為TRUE代表成績大於等於60。請使用[.]
一次完成這兩件事。
[.]
的.
若使用數字向量來取元素,數字向量不一定要由小到大排列:
a3 <- c('Q','B','W','U','J','D','L','V','X','G')
a3
a3[c(2,4,5)]
a3[c(5,2,4)]
我們可以輕易重新排列元素:
revert <- seq(10,1,by=-1)
revert
a3 <- c('Q','B','W','U','J','D','L','V','X','G')
a3
a3[revert]-> a3
a3
課堂練習
1.
以下各題以課堂調查的classSurvey資料框(data frame)為主:
library(readr)
classSurvey <- read_csv("https://raw.githubusercontent.com/tpemartin/github-data/master/classSurvey.csv")
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()
呈現。