關卡 1

這門課程的目標是講解Robject的入門操作。

關卡 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(NotANumber)的結果。請同學試試看輸入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

我們可以在說明文件上,閱讀DefaultS3method之下的那段說明程式碼:seq(from=1,to=1,by=((to-from)/(length.out-1)),length.out=NULL,along.with=NULL,...)這段說明文字顯示了seq可以接受五個參數,分別為:fromtobylength.outalong.with

關卡 28

對於個別參數的使用方法,我們可以閱讀在Argument之下的細節說明。比如說,from,tofrom,tothestartingand(maximal)endvaluesofthesequence.Oflength1unlessjustfromissuppliedasanunnamedargument.這段文字就說明了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

我們也可以透過指定參數名稱的方式來告訴Rseq的參數是什麼。舉例來說,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知道此序列中,argumentlength.out的值是10。

關卡 36

若是不使用序列,而是想要重複某一個數字,則可以用rep。請同學試試看:rep(2,times=10)

rep(2, times = 10)

關卡 37

rep也可以作用在一個序列上。如果給了argumenttimes定值,那R會將整個序列重複times次,並接起來。請同學試試看:rep(x,times=2)

rep(x, times = 2)

關卡 38

如果rep沒有指定在argumenttimes,而是在argumenteach,那R會將向量的每一個值,個別重複each遍之後,再接起來。請同學試試看:rep(x,each=2)

rep(x, each = 2)

關卡 39

在R中,整理資料的時候很常會將seqrep的搭配使用。有興趣的同學可以在後續的實例教材中,看看在整理資料的過程如何應用這兩個函數解決問題。

關卡 40

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

關卡 41

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

關卡 42

邏輯值「真」常用TRUET來代表。「假」則用FALSEF代表。第三種在邏輯向量會出現的值,就是NA(NotAvailable)。注意:這裡的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]