關卡 1
這門課程的目標是講解R object的入門操作。
關卡 2
R 的object結構是針對資料分析所設計的。所以最簡單 的object,就是一連串的數字。
關卡 3
這讓R 和其他的程式語言不同,因為一般的程式語言 最簡單的object會是一個數字。
關卡 4
R 這樣設計的理由是因為在資料分析的應用中,一定是同時處理多筆資料,而不會只有單一筆資料。
關卡 5
要用R 建立一個內容為10.4, 5.6, 3.1和6.4的向量, 最常用的方式就是輸入:c(10.4, 5.6, 3.1, 6.4) 請同學依照這樣的語法建立一個這樣的向量,並且把它存為變數x。
x <- c(10.4, 5.6, 3.1, 6.4)關卡 6
請問同學,上述輸入的語法是assignment還是expression呢?
assignment
關卡 7
在R 中,c()可以接受任意數量的向量參數,並依照順序將它們串接成一個單一向量。 舉例來說:c(x, 1)會在剛剛我們建立的x 後面再接一個1 。 而c(x, 2, 3)則會在x 之後接上2 和3 。 請同學依照上述規則,撰寫一個expression,內容是建立一個在x 後面接上x 的向量。
c(x, x)關卡 8
在R 中,大部份的運算都是向量式的。舉例來說,加法+在R 中就屬於向量式。 請同學輸入:c(1, 2, 3) + c(2, 4, 6) 並觀察結果。
c(1, 2, 3) + c(2, 4, 6)關卡 9
計算結果中的第一個值,就是輸入的兩個向量中,第一個值的相加。 以此類推,一直到第三個值都維持這樣的規律。這就是「向量式」的意思。
關卡 10
當相加的兩個向量長度不同時,R 會自動重複比較短的向量,補到和較長的向量相同的長度,然後用 一樣的方式去做計算。請同學輸入2 + c(1,2,3)試試看。
2 + c(1,2,3)關卡 11
向量式運算可以讓我們在處理資料時更加容易。 在R 之中,除了加減乘除之外,許多常用的數學算式都是向量式的。例如:log、exp、sin、 cos、tan和sqrt。
關卡 12
然而,並不是所有的運算都是向量式的。 舉例來說,給定一個向量x ,max(x)會傳回x 中最大的值,而min(x)則會傳回x 中最小的值。 若想要在分析數據的時知道數值的範圍,這兩個函數就可以派上用場。 請同學寫一個expression來建立兩個值的向量,而且第一個值是x 的最小值,第二個值則是x 的最大值。
c(min(x), max(x))關卡 13
在R 中有,函數range能直接傳回輸入向量的範圍(最小到最大)。 請同學使用range,再算一次x 的範圍。
range(x)關卡 14
在R 中,函數sum(x)會傳回x 所有值的加總。 函數length(x)則能直接傳回x 的長度。 現在,請同學利用sum和length計算x 的平均值。
sum(x) / length(x)關卡 15
R 也內建許多統計函數。 例如mean(x)可以計算x 的平均值。透過mean、sum和length,我們就能計算x 的樣本變異數:sum((x - mean(x))^2) / (length(x)-1)。 但是R 也有內建的函數來簡化計算工作。 透過var(x),我們就能簡單用短短的函數計算樣本變異數。
關卡 16
現在,請利用var計算x 的樣本變異數。
var(x)關卡 17
請利用sd計算x 的樣本標準差。
sd(x)關卡 18
而sort(x)則會產生一個和x 長度一樣的向量,但向量中的值是由小到大排列。 請同學試試看:sort(x)
sort(x)關卡 19
在數學中,計算中輸入的x ,代表的可能是整數、實數或甚至是複數。 而R 中的數學計算,則會自動根據x 的屬性做出調整。
關卡 20
舉例來說,如果輸入sqrt(-17),我們會得到NaN(Not A Number)的結果。 請同學試試看輸入sqrt(-17)。這裡的sqrt代表的是數學上開根號的運算。
sqrt(-17)關卡 21
在數學中,對負數開根號,在實數中是沒有答案的。
關卡 22
但是,若我們改為輸入sqrt(-17 + 0i),這時候因為輸入的是一個複數, R 會自動調整運算行為,不會再回傳一個NaN。請同學試試看。
sqrt(-17 + 0i)關卡 23
R 也具備有簡易的功能,可以產生一些附帶有規則的序列。 例如:1:10就會產生自1 至10的序列。 這樣的功能,在整理資料時十分實用。 舉例來說,如果需要取出第5筆到第100筆的資料,就會用到類似的語法。 請同學利用:建立一個從20到40的序列。
20:40關卡 24
在R 中,:這個運算子的優先層級很高。 也就是說,如果看到:2 * 1:10這段expression,會優先處理1:10的部分,然後再將結果乘以2。 我們來讓同學試試看,請輸入:2 * 1:10。
2 * 1:10關卡 25
跟各位介紹一個更被廣泛運用,產生向量的方式:seq。 seq(1, 10) 在R 中所代表的,其實就是1:10。 請試試看輸入seq(1, 10)。
seq(1,10)關卡 26
seq本質上就是一個「函數」,而seq(1,10)這段expression中,我們將1 和10稱為此函數的參數(Argument)。 讓我們來看一下seq可以接受幾個參數。 請同學用之前介紹的方式,打開seq的說明文件。
?seq關卡 27
我們可以在說明文件上,閱讀 Default S3 method 之下的那段說明程式碼: seq(from = 1, to = 1, by = ((to - from)/(length.out - 1)), length.out = NULL, along.with = NULL, ...) 這段說明文字顯示了seq可以接受五個參數,分別為:from、to、by、length.out和along.with。
關卡 28
對於個別參數的使用方法,我們可以閱讀在Argument之下的細節說明。 比如說,from, to from, to the starting and (maximal) end values of the sequence. Of length 1 unless just from is supplied as an unnamed argument. 這段文字就說明了from和to的用法。
關卡 29
有時候,說明文字不如程式碼來得清楚,請直接翻閱到說明文件最底下,查看Examples之中官方所提供的seq的範例。
關卡 30
如果要運行這些範例,可以簡單輸入:example(seq),請同學跟著輸入。
example(seq)關卡 31
在R 中,seq的參數共有:from、to、by、length.out和along.with五種。 如果我們不指定,而是依照順序填入:seq(1, 10),那就代表from是1 、 to是10、,而by等其他Argument則使用預設參數。
關卡 32
我們也可以透過指定參數名稱的方式來告訴R seq的參數是什麼。 舉例來說,seq(to = 10, from = 1)會告訴R 參數from的值是1 ,而to則是10。 因此,計算結果將會和seq(1,10)相同。請同學試試看。
seq(to = 10, from = 1)關卡 33
而利用seq所產生的序列間隔也不一定要是1 。seq函數可以透過by這個參數控制間隔, 如果希望間隔是0.5,所以只要輸入seq(1, 10, by = 0.5)即可產生。請同學試試看。
seq(1, 10, by = 0.5)關卡 34
而我們也可以透過指定開頭、間隔和長度來產生序列。 在seq中,這對應到from、by和length.out這三個參數。 請同學寫一個expression,產生一個從1 開始,間隔為2 ,長度為10的序列。參數請透過 名稱來給定。
seq(from = 1, by = 2, length.out = 10)關卡 35
R 很聰明,在指定argument時不須指定全名,只要給出前面幾個可以讓R 辨別argument名稱的字母即可。 舉例來說:seq(from = 1, by = 2, length = 10)也可以讓R 知道此序列中,argument length.out的值是10。
關卡 36
若是不使用序列,而是想要重複某一個數字,則可以用rep。 請同學試試看:rep(2, times = 10)
rep(2, times = 10)關卡 37
rep也可以作用在一個序列上。如果給了argument times定值,那R 會將整個序列重複times次,並接起來。 請同學試試看:rep(x, times = 2)。
rep(x, times = 2)關卡 38
如果rep沒有指定在argument times,而是在argument each, 那R 會將向量的每一個值,個別重複each遍之後,再接起來。 請同學試試看:rep(x, each = 2)。
rep(x, each = 2)關卡 39
在R 中,整理資料的時候很常會將seq和rep的搭配使用。 有興趣的同學可以在後續的實例教材中,看看在整理資料的過程如何應用這兩個函數解決問題。
關卡 40
除了數值之外,邏輯值也是很常見的。 類似數值,R 最基礎的object之一,就是邏輯向量。 在R 中,我們看到的一個值,其實只是一個長度為1 的向量。
關卡 41
邏輯向量常常表示資料中如:「是、否」、「男、女」之類等二分法的選項。 除此之外,也很常用在程式碼的流程控制。
關卡 42
邏輯值「真」常用TRUE或T來代表。「假」則用FALSE或F代表。 第三種在邏輯向量會出現的值,就是NA(Not Available)。 注意:這裡的T和F所對應到的TRUE或FALSE變數只是預設值,並不是保留。如有需要,是可以更改T和F的內容的!
關卡 43
我們可以利用各種不同「條件類型的expression」來建立邏輯向量。 舉例來說,有一個序列x ,我們就可以利用x > 5來建立一個長度和x 相同的邏輯向量。請同學試試看。
x > 5關卡 44
從結果可以看到,R 會拿x (c(10.4, 5.6, 3.1, 6.4))中的值一個個的和5 比較大小。 比較大的就是TRUE,而比較小的即是FALSE。
關卡 45
依此類推,可用於建立邏輯向量的「條件」分別有:大於>、大於等於>=、小於<、小於等於<=、相等==和不相等!=。 這類邏輯向量在整理資料做資料篩選時,是很常用到的。
關卡 46
另外,「且」&以及「或」|這兩個邏輯運算子也是很常用的。它們可以 在兩個邏輯向量中做運算。請同學試試看:x > 5 & x < 10。
x > 5 & x < 10關卡 47
輸出結果顯示,在x (c(10.4, 5.6, 3.1, 6.4))中,介於5 和10之間的數值會顯示為TRUE,否則顯示為FALSE。 在篩選資料時,若是篩選條件較為複雜,需要用到多個條件來組合而成時,就會用到&以及|。
關卡 48
當資料的值無法取得時,R 就會給它一個特殊的記號:NA。 所有和NA相關的運算結果,通常都會是NA。 就常識來看,這很合理。因為「無法取得的數字」加上1 ,結果依舊會是「無法取得」。
關卡 49
我們可以利用is.na來判斷一個向量裡面是否有NA存在。 請同學試試看is.na(x)。
is.na(x)關卡 50
在R 中,is.na(x)的結果都是FALSE,因為x 的資料裡面沒有NA。 因此,我們來玩一個有NA的向量吧! 請試試看:is.na(c(1,2,NA,3))
is.na(c(1,2,NA,3))關卡 51
在R 之中,我們已經看過兩種特別的記號,分別為:NA和NaN。 NA代表的是缺失值,而NaN 大多來自於數學運算中沒有定義的行為。 例如:sqrt(-17)、0/0和Inf - Inf。在R 中,無限大就是Inf。 R 對此類的數學處理是很聰明的。 同學們可以試試看使用R 計算Inf + 1 的結果。
Inf + 1關卡 52
雖然可以理解NA和NaN的不同,但是is.na會將兩者都定義成TRUE。 請同學試試看:is.na(c(NA, NaN, 1))
is.na(c(NA, NaN, 1))關卡 53
有時候,我們需要處理文字類型的object。這些object通常被用於指定繪圖的標題、或是處理類別形變數,如:國籍、行政區等等。 在R 之中,這類的資料是透過單引號'或雙引號"來建立的。而這類的資料也常被人稱為:「字串」。
關卡 54
舉例來說,如果直接輸入x而不用雙引號包覆它,R會自動將x當成變數名稱,進而回傳x 的內容。 請同學試試看輸入:x
x關卡 55
然而,若是輸入的為"x",那R 就會認為這是一個只有一個字元、內容為“x”的字串。 請同學試試看輸入:"x"
"x"關卡 56
為了方便教材的設計,後續操作swirl的時候,請盡量使用"來建立字串。
關卡 57
這類文字類型的object,在R 中,\符號代表字串中的跳脫符號。 舉例來說,如果我們要輸入一個包含雙引號的字串,有兩種方法:一種是用 單引號'來包覆雙引號,另外一種就是在雙引號之前插入\。請同學試試看 用跳脫符號的方式,輸入一個字串,內容只有一個雙引號。
"\""關卡 58
在R 中,paste為經常用來做字串處理的函數。 我們可以丟任意個Argument 給paste,結果R 會把這些argument以字串的形式接成一個字串。 請同學試試看:paste("a", "b")
paste("a", "b")關卡 59
請同學試試看:paste(c("X", "Y"), 1:10)
paste(c("X", "Y"), 1:10)關卡 60
結果中會發現,1:10被自動轉換成字串了。 這又是一個R 自動判斷形態的例子。 同時,也可以注意到c("X", "Y")重複了五次,這是因為paste也是一個向量化的函數。
關卡 61
另一個值得注意到的是paste在串接字串時,在字串中間會留下一個預留的空格。 如果不希望在字串間出現空格,可以改為使用paste0。 paste0和paste為幾乎一樣的函數。差別在於paste0預設在串接字串時,中間是不會有空格的。 同學請試試看:paste0(c("X", "Y"), 1:10)
paste0(c("X", "Y"), 1:10)關卡 62
最後,我們要介紹一個在整理資料時被廣泛運用的功能:如何在向量中挑選出一部份的資料。
關卡 63
第一種方法,使用坐標。 在R 之中,如果我們要挑選序列x 中的第一個和第三個位置的值,只要使用即可:x[c(1,3)]。 請同學試試看。
x[c(1,3)]關卡 64
第二種方法則是利用邏輯向量。 舉例來說,如果要挑選x 之中超過5 的值,即可透過x[x > 5]取得。請同學試試看。
x[x > 5]關卡 65
第三種方法為削去法。 如果我們要挑序列x 中除了第二個數值之外全部的值,則可以使用x[-2]。
x[-2]關卡 66
最後一個方法較為特別,在介紹方法之前,我們要先介紹在R 中names的概念。 在R 的向量中,可以針對每一個值進行命名。 舉例來說,我們可以透過:names(x) <- c("a", "b", "c", "d")來幫x 的每個值命名。 請同學試試看。
names(x) <- c("a", "b", "c", "d")關卡 67
現在請將x 印到螢幕上看看。
x關卡 68
可以看到R 在顯示每個x 的值時,也會在上一行對應的位置中印出它的名字。
關卡 69
所以如果想要選取名稱為c("b", "d")的值,就只要輸入:x[c("b", "d")]。 請同學試試看。
x[c("b", "d")]關卡 70
上述內容為關於R 資料結構的入門。 接下來,只要再學會對於矩陣和data.frame的操作,就可以開始解決實際的問題了!
關卡 71
最後請同學試試看用今天所學的方法,整理台電的公開數據。 請同學在完成之後存檔,並輸入submit()來檢查結果是否符合預期。 如果同學在檔案中看到亂碼,請選取Rstudio 左上角的File -> Reopen With Encoding… -> 選取:UTF-8
# 社會服務業自民國87至民國91年的年度用電量(度)
year1 <- 87:91
power1 <- c(6097059332, 6425887925, 6982579022, 7323992602.53436, 7954239517)
# 製造業自民國87至民國91年的年度用電量(度)
power2 <- c(59090445718, 61981666330, 67378329131, 66127460204.6482, 69696372914.6949)
# 請同學選出年度(`year1`)中,社會服務業的的用電量超過`7e9` 的年份。
# (`7e9`是R 的科學符號,代表`7 * 10^9`)
year1.answer1 <- year1[power1 > 7e9]
# 接著請同學計算「社會服務業從民國87年到91年的平均用電量」
power1.mean <- mean(power1)
# 請計算「社會服務業從民國87年到91年用電量的標準差」
power1.sd <- sd(power1)
# 在統計中,我們常常會計算一筆數據的「標準分數」,也就是將數據減去平均數後除以標準差。
# 請同學計算「社會服務業從民國87年到91年用電量的標準分數」
power1.z <- (power1 - mean(power1)) / sd(power1)
# 同樣的道理,請同學算出「製造業自民國87年至民國91年用電量的平均數、標準差和標準分數」
power2.mean <- mean(power2)
power2.sd <- sd(power2)
power2.z <- (power2 - mean(power2)) / sd(power2)
# 最後,請同學找出年度中,「社會服務業的用電量」,超過「製造業的10%用電量」的年份
year1.answer2 <- year1[power1 > 0.1 * power2]