關卡 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]