關卡 1

在R中,我們操作的所有變數,都是一種R物件(Object)。這一堂課程中,就是要簡介R的物件結構。

關卡 2

在所有物件中,最基礎的「原子」物件,就是在上一堂課中介紹的各種向量。其他的物件都是有這些原子物件組合而成。

關卡 3

這些向量物件有兩個很重要的屬性:modelengthmode代表這個向量的值型態,總共有:logicalintegernumericcomplexcharacterrawlength代表這個向量的值的個數。

關卡 4

同學可以用modelength這個函數來查詢一個向量的型態和長度。請同學試試看:mode(x)

mode(x)

關卡 5

請問x的型態是?

numeric

關卡 6

接著,請試試看length(x)

length(x)

關卡 7

請問x的長度是?

5

關卡 8

R也可以建立一種叫做list的向量,這是「R物件」的向量。換句話說,每一個值都是R物件,都有自己的modelength等屬性。我們會在一些複雜的統計模型中,見到這樣的資料型態。舉例來說,在R中如果要建立一個迴歸模型,會使用:g<-lm(dist~speed,cars)這樣的程式碼會利用車速當解釋變數、煞車距離當應變數,建立一個迴歸模型。這裡我們先不管lm怎麼用,而是要看看g這個物件的結構。同學只要掌握這個課程的內容,未來就可以輕鬆的探索各種機器學習或統計分析演算法的輸出結果。

關卡 9

請同學檢查g的型態

mode(g)

關卡 10

請同學檢查g的長度

length(g)

關卡 11

在上一個章節中,我們有介紹可以使用如g[1:2]的方式來拿出g的第一個到第二個值。而這樣的輸出結果,還是會和g有同樣的mode。這裡請同學看看g[1:2]的結果。

g[1:2]

關卡 12

同學會在Rconsole看到一些數字與奇妙的文字。在最上面的$coefficients,表示g[1:2]這個向量的第一個值(同時也是g的第一個值),是有名字的。他的名字是:"coefficients"。接著,由於g[1:2]的第一個值是一個有名字的numeric向量,所以R就把這個向量所有的名字和值一起顯示在console。也就是說,這個numeric向量的第一個值是-17.579095,而名字是"(Intercept)"。第二個值是3.932409,而名字是"speed"

關卡 13

接著,$residuals表示g[1:2]的第二個值也是有名字的,而且它的名字是"residuals"。由於這個值也是一個有名字的numeric向量,所以R就把值和名字同時顯示到console上。所以我們就可以知道,這個numeric向量的第一個值的名字是"1",值是3.849460。以此類推。

關卡 14

然而整個RConsole的顯示告訴我們g[1:2]仍然是一個list,因為R只有在顯示list的內容才會帶有$coefficients$residuals這種標記。如果只是一個numeric向量,就不會顯示出$coefficients$residuals

關卡 15

請同學輸入list(1,a=2)來看看R是如何顯示list,以及比較當值有附帶名字,或是沒有附帶名字時,輸出的不同。

list(1, a = 2)

關卡 16

在一開始,R顯示了[[1]],然後才顯示一個值為1的numeric向量。開頭的[[1]]不只說明了這個物件是一個list,也說明接下來顯示的是第一個值的內容。

關卡 17

接著,R顯示了$a,後才顯示了一個值為2的numeric向量。開頭的$a因為位置在第二,所以代表這是這個list物件的第二個值。同時,這個值的名字是"a"

關卡 18

但是如果我們想拿出,g的第一個值,並且是這個物件的本身,而非被包在一個list中,我們需要用:g[[1]]。請同學試試看。

g[[1]]

關卡 19

請同學查詢g[[1]]的型態

mode(g[[1]])

關卡 20

請同學查詢g[[1]]的長度

length(g[[1]])

關卡 21

這裡再解釋一次g[1]g[[1]]的差異。使用g[1]時,R取出向量的第一個元素,並且維持list的結構,所以g[1]的結果還仍是list。使用g[[1]]時,R會打破list的結構,再取出向量的第一個元素,所以g[[1]]的型態會是存放在list裡面的R物件的型態。所以在上述的例子中,g[1]的型態是list,而g[[1]]的型態就是numeric。這是因為g這個list的第一個存放的R物件是numeric向量。

關卡 22

一般來說,對R物件使用[]之後,會取得會和該物件相同的物件。舉例來說,a[1]的型態會和a一樣。而[[]]就沒有類似的特性了。

關卡 23

經過這些練習,相信同學也會理解list這個「R物件的向量」是什麼意思。list向量最有用的地方,在於它可以裝不同型態的值。以g為範例,雖然它大部分的值的型態都是numeric,但是有些物件的型態會是call和list。這讓R的開發者能更有彈性的建立一些複雜的模型。同時同學在學會list之後,也更有能力來了解各種R套件所建立的模型物件。

關卡 24

請同學檢查看看g[[10]]的型態

mode(g[[10]])

關卡 25

這裡的g[[10]]其實是記載著產生g的程式碼。在R裡面,這樣的程式碼是存成call型態的物件。我們現在只要知道這是一種call就可以了。至於call是什麼東西,要等到同學需要開始深入的學習R的原始碼、運作機制時,才需要弄懂。我們現在只要知道,list可以裝所有R的物件就可以了。

關卡 26

另一個我們需要知道的事情,就是可以為list命名。舉例來說,我們除了用g[[1]]來取得第一個值之外,也可以用g[["coefficients"]]來取得第一個值。因為g這個向量是被命名的,而第一個名字就是"coefficients"。請同學試試看。

g[["coefficients"]]

關卡 27

適當的命名,可以讓程式碼更易讀。舉例來說,若我們知道g是一個迴歸模型,我們也知道迴歸模型通常就是一個參數向量,那我們就會預期:g[["coefficients"]]就是這個迴歸模型的參數。(在統計學課本中,各種模型的參數通常稱作:“coefficients”。

關卡 28

我們可以更改一個向量的長度。舉例來說,現在x是一個長度是5、型態是numeric的向量。我們可以利用:length(x)<-10把x的長度改成10。請同學試試看。

length(x) <- 10

關卡 29

現在我們可以來看看x的值。,請同學輸入:x

x

關卡 30

我們也可以直接在x的指定位置塞入新的值,並且藉此增加x的長度。舉例來說:x[7]<-7可以讓x的第7個位置的值變成7。請同學試試看。

x[7] <- 7

關卡 31

現在我們可以來看看x的值。,請同學輸入:x

x

關卡 32

由於x本來的長度就已經超過7所以並沒有延長。現在我們改程式試試看:x[13]<-13

x[13] <- 13

關卡 33

現在我們可以來看看x的值。,請同學輸入:x

x

關卡 34

如果我們要縮短x的長度,可以運用如:x2<-x[c(1,3,5,7,9,11,13)],這樣x2就是縮短的x。請同學試試看。

x2 <- x[c(1,3,5,7,9,11,13)]

關卡 35

現在我們可以來看看x2的值。,請同學輸入:x2

x2

關卡 36

x2只剩下原本在x奇數位置的值了。在整理資料時,我們常常需要這樣的技巧,來從資料中選出我們真正要分析的部份,並且將資料調整成我們需要的長度。

關卡 37

所有的R物件,都有「屬性」(attributes)。我們可以用attributes這個函數來印出一個R物件的屬性。請同學試試看:attributes(g)

attributes(g)

關卡 38

請問同學,根據剛剛的輸出結果,attributes(g)的屬性應該是哪一種向量?

list

關卡 39

在下一個題目之前,我想請同學先輸入names(g)來查詢g的名字。並且和attributes(g)的結果做比對。

names(g)

關卡 40

在剛剛attributes(g)的輸出中,同學應該會看到一個帶有名字的list。請同學記得,所有R物件的attributes都是帶有名字的list。

關卡 41

通常這個物件的名字,就是attributes(g)這個list中,名字為"names"的值。而且值一定要是character向量。在R中,我們可以用attr(g,"names")來取得名字是“names”的屬性。請同學試試看。

attr(g, "names")

關卡 42

上一題的輸出結果,就是g這個list的名字,也就是names(g)的結果。

關卡 43

讓我們回到attributes(g)的輸出。除了第一個值是名字為"names"的character向量之外,第二個值是一個名字是"class"的character向量。character向量的值是"lm"。請同學試試看:attr(g,"class")

attr(g, "class")

關卡 44

了解像attributes這樣的功能,在探索一些複雜的R模型物件時,是非常好用的。我們在之後深入探討matrixdata.frame等進階物件的時候,也會需要了解attributes的相關的知識。現在,同學只要知道所有的R物件都有attributes就可以了。

關卡 45

而名稱為“class”的屬性是非常重要的,因為它牽涉到R的物件導向設計。這部份請讓我們到更進階的章節再跟同學說明。

關卡 46

由於“names”和“class”這兩個屬性是如此的重要,所以在R中有設計了classnames這兩個函數,可以讓使用者很方便的來修改一個R物件的names和class。請同學試試看:names(g)

names(g)

關卡 47

再請同學試試看:class(g)

class(g)

關卡 48

這個課程簡介了R的物件系統。希望未來同學在接觸到沒學過得套件時,可以有系統得來摸索R套件的輸出。

關卡 49

最後我們請同學用這個課程所學的內容,處理一個PCA的結果。請同學在完成之後存檔,並輸入submit()來檢查結果是否符合預期。如果同學在檔案中看到亂碼,請使用Rstudio左上角的File->ReopenWithEncoding…->選取:UTF-8

#' 以下內容改自prcomp 的範例程式碼
#' 
#' PCA(Principle Components Analysis) 是一個資料分析時常用的技術,
#' 它的原理會在後面的課程講解。
#' 在R 中,我們可以利用prcomp這個指令對USArrests這筆資料進行PCA 的分析,
#' R 會吐回一個計算後的物件給我們。
pca <- prcomp(USArrests, scale = TRUE)

#' 請同學找出pca的「型態」。你的答案只可能是:「"character"」、「"numeric"」或「"list"」
answer1 <- mode(pca)

#' 請同學將pca的長度寫入變數answer2
answer2 <- length(pca)

#' 請同學將pca的名字寫入變數answer3
answer3 <- names(pca)

#' pca 的元素中,有一個是各個principal components的standard deviations。
#' 請同學參考help(prcomp)的說明的Value章節
#' 將各個principal components的standard deviations
#' 寫入變數answer4
answer4 <- pca$sdev

#' pca 的元素中,有一個是PCA的中心(center)。請同學參考help(prcomp)的說明,
#' 將該元素寫入變數answer5
answer5 <- pca$center