關卡 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 之中,除了加減乘除之外,許多常用的數學算式都是向量式的。例如:logexpsincostansqrt

關卡 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 的長度。 現在,請同學利用sumlength計算x 的平均值。

sum(x) / length(x)

關卡 15

R 也內建許多統計函數。 例如mean(x)可以計算x 的平均值。透過meansumlength,我們就能計算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

跟各位介紹一個更被廣泛運用,產生向量的方式:seqseq(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可以接受五個參數,分別為:fromtobylength.outalong.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. 這段文字就說明了fromto的用法。

關卡 29

有時候,說明文字不如程式碼來得清楚,請直接翻閱到說明文件最底下,查看Examples之中官方所提供的seq的範例。

關卡 30

如果要運行這些範例,可以簡單輸入:example(seq),請同學跟著輸入。

example(seq)

關卡 31

在R 中,seq的參數共有:fromtobylength.outalong.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中,這對應到frombylength.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 中,整理資料的時候很常會將seqrep的搭配使用。 有興趣的同學可以在後續的實例教材中,看看在整理資料的過程如何應用這兩個函數解決問題。

關卡 40

除了數值之外,邏輯值也是很常見的。 類似數值,R 最基礎的object之一,就是邏輯向量。 在R 中,我們看到的一個值,其實只是一個長度為1 的向量。

關卡 41

邏輯向量常常表示資料中如:「是、否」、「男、女」之類等二分法的選項。 除此之外,也很常用在程式碼的流程控制。

關卡 42

邏輯值「真」常用TRUET來代表。「假」則用FALSEF代表。 第三種在邏輯向量會出現的值,就是NA(Not Available)。 注意:這裡的TF所對應到的TRUEFALSE變數只是預設值,並不是保留。如有需要,是可以更改TF的內容的!

關卡 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/0Inf - 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在串接字串時,在字串中間會留下一個預留的空格。 如果不希望在字串間出現空格,可以改為使用paste0paste0paste為幾乎一樣的函數。差別在於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->ReopenWithEncoding…->選取: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]