以下是綜合過去一段時間斷斷續續寫下的備忘與這幾天重新複習 R 基本語法後所整理的筆記, 參考了下面幾本書 :
- R 語言資料分析活用範例詳解 (方匡南等, 碁峰出版)
- R 語言-邁向 Big Data 之路 (洪錦魁, 蔡桂宏, 上奇出版)
- 應用 R 語言於資料分析-從機器學習, 資料探勘, 到巨量資料 (李仁鐘, 松崗)
- 利用 R 語言打通大數據的經脈 (黃文, 王正林, 佳魁出版)
- R 錦囊妙計 (Paul Teeter, 歐萊里出版)
- R 軟體資料分析基礎與應用 (旗標)
# R 語言安裝
# 在樹莓派上安裝 R 語言
R 語言線上文件參考 (HTML) :
# https://stat.ethz.ch/R-manual/R-devel/library/base/html/
R 語言的特性 :
- R 是免費開源 (GPL) 的跨平台高階語言, 具有強大的統計分析與圖形處理功能.
- R 是直譯的動態語言, 變數使用前不須宣告資料型態.
- R 是指令式 (Imperative) 語言, 按照敘述流程一行一行執行.
- R 是函數式 (Functional) 語言, 函數是第一級 (first-class) 物件, 函數可當變數並遞迴呼叫.
- R 是物件導向 (Object-Oriented) 語言, 所有的資料都以物件型態儲存.
- R 程式在運算時會將資料全部載入記憶體, 因此只要記憶體夠大, R 的執行速度很快.
一. 敘述與註解 :
R 語言的敘述以跳行為界, 不須用分號結束 (有加分號結尾也不會錯誤). 在 R 控制台若敘述不完全就按 Enter 鍵跳行會在下一行開頭出現 + 表示需要繼續輸入未完成部分 :
> 1+2+
+ 3+4+
+ 5
[1] 15
R 語言以 # 作為程式註解標記, # 後面的敘述會被直譯器認為是註解不予執行. 輸出訊息最前面的 [1] 表示 15 是向量的第一個元素索引, 如果元素很多跳行列印時, 開頭的索引有助於找尋元素位置, 例如呼叫內建函數 runif() 產生 20 個均勻分布的隨機數時, 每列輸出 6 個隨機數, 可利用前面中括號內的索引找到特定元素 :
>x <- p="" runif="">>x
[1] 0.22747749 0.82250470 0.99277969 0.26681451 0.33374732 0.14401908
[7] 0.99045832 0.79202189 0.40882923 0.07766307 0.29366118 0.37315030
[13] 0.22812758 0.47525042 0.39673555 0.43922495 0.69614128 0.42930582
[19] 0.73167837 0.65415575
->
二. 變數與函數名稱 (識別字) :
R 語言識別字的命名規則如下 :
- 識別字由英文字母, 數字 (0~9), 小數點符號, 或底線組成.
- 英文字母有分大小寫, Tony 與 tony 是不同的識別字.
- 只能以字母或小數點開頭, 若以小數點開頭, 後面不可以是數字或底線.
- 不可使用 R 語言保留字.
- 函數名稱與變數名稱相同無妨, 函數 f() 與變數 f 可同時存在.
R 的保留字一共有 19 個如下, 這些都不可以當變數或函數名稱 :
其中 9 個是流程控制與函數語法保留字 :
if | else | repeat | while | function | for | in | next | break |
其次是 10 個特殊符號保留字 :
TRUE | FALSE | NULL | Inf | NaN | NA |
NA_integer | NA_real | NA_complex | NA_character |
其中 TRUE/FALSE 是資料型態 logical 的兩種值域, NULL 是空物件, Inf 表示無限大值 (除以 0 情況), NaN 表示非數字, NA/NA_integer/NA_real/NA_complex/NA_character 用來表示五種遺漏值 (沒有內容, 例如問卷中的未填欄位). 例如 :
> 1==1
[1] TRUE
> 1==2
[1] FALSE
> 1/0
[1] Inf
> -1/0
[1] -Inf
> Inf-Inf
[1] NaN
另外還有 5 個內建常數也不要使用作為識別字, 雖然作為變數名稱不會出現錯誤, 但會破壞這些內建常數的預設值 (很奇怪, 常數不應該允許被修改才對) :
pi | LETTERS | letters | month.abb | month.name |
> pi
[1] 3.141593
> LETTERS
[1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
[20] "T" "U" "V" "W" "X" "Y" "Z"
> letters
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
[20] "t" "u" "v" "w" "x" "y" "z"
> month.abb
[1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"
> month.name
[1] "January" "February" "March" "April" "May" "June"
[7] "July" "August" "September" "October" "November" "December"
R 語言變數的指定或賦值 (assignment) 可以用如下四種方式 :
x = 5
x <- 5 (建議用法)
5 -> x
asign("x", 5)
其中第二種方式是 R 語言建議的用法, 而 "=" 則不建議使用, 因為等號賦值只在 R Console 互動模式下輸入完整敘述時可用, 而且某些情況下會有混淆問題, 例如在 SQL 命令時, "=" 是比較是否相等, 這容易與賦值造成混淆. 參考 :
# https://stat.ethz.ch/R-manual/R-patched/library/base/html/assignOps.html
不論是 "<-" 或 "=" 都可以用來同時賦值多個變數, 例如 :
> a <- b <- 2
> a
[1] 2
> b
[1] 2
> a = b = 2
> a
[1] 2
> b
[1] 2
合法的變數名稱範例如下 :
> name <- "tony"
> name
[1] "tony"
> .name <- "Tony"
> .name
[1] "Tony"
> p2p <- "peer to peer"
> 名字 <- "Tony" #可以使用中文當變數名稱 (各語言字母均可)
> 名字
[1] "Tony"
> assign("x",1)
> x
[1] 1
雖然允許使用中文作為變數名稱, 但是為了程式可攜性, 最好只使用英文字母.
下面則是不合法的變數名稱 :
> if=TRUE #不可以使用保留字 if
錯誤: 未預期的 '=' in "if="
> NA="" #不可以使用保留字 NA
Error in NA = "" : (do_set) 賦值公式左側不正確
>._name="tony" #小數點後面不可以是底線
另外, R 語言以跳行作為一個敘述結束標記, 若跳行時敘述不完整, 則會出現 "+" 符號表示繼續輸入未完部分. 若要在一行裡執行多個敘述, 則個敘述之間用分號 ";" 隔開即可, 例如 :
> v1 <- 1:10; v2 <- c("A", "B")
> v1
[1] 1 2 3 4 5 6 7 8 9 10
> v2
[1] "A" "B"
三. 資料型態 :
R 是物件導向語言, R 所有的東西不論是常數, 變數, 函數, 甚至表示式都是物件. R 常用的資料物件有下面幾種 :
> 5
[1] 5 #純量 5 在 R 中是單一元素的向量
> length(5) #查詢向量長度 (元素個數)
[1] 1
> 5[1] #索引 1 就是資料本身
[1] 5
> 5[2] #索引 2 無值=NA
[1] NA
R 的向量資料有如下 6 種類型, 稱為原型向量 (atomic vector), 此乃相對於被稱為泛型向量 (generic vector) 的列表 (list) 而言, 泛型向量例如 list 的元素允許異質, 亦即可以是任何資料物件 (vector, list, array, matrix, data.frame 等等), 但向量的元素必須是同質性資料 (即全部元素之資料型態必須相同) :
注意, 類型 numeric 包含 integer 與 double 兩種數值, 預設是 double (實數), 可用浮點數如 3.14159 或科學記號 3.14159e1 表示. 向量可用 class(), typeof(), mode(), 或 storage.mode() 這四個內建函數查詢其類型. 其次, R 與數學習慣一樣使用小寫 i 來表示虛數, 這與 Python 偏向工程界使用 j 來表記虛數有所不同.
常數看似純量 (scaler), 但其實是只含有一個元素的向量, 例如在 R console 輸入數字或字串 :
> 5 #單一元素的向量 (整數)
[1] 5
1. 使用冒號運算子建立向量 :
建立向量的第一個方法是利用冒號運算子來產生間隔為 1 的向量, 例如 1:50 表示含有元素 1~50 的整數向量, 例如 :
> 1:50
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
[25] 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
[49] 49 50
冒號運算子也可以用在浮點數, 間隔同樣是 1:
> 2.2:9.9
[1] 2.2 3.2 4.2 5.2 6.2 7.2 8.2 9.2
> 9.9:2.2
[1] 9.9 8.9 7.9 6.9 5.9 4.9 3.9 2.9
可以將向量指定給變數, 以索引來存取元素. 與 Python 或 C 語言族系不同的是, R 語言的索引是從 1 起算的, 若索引超出範圍將輸出 NA, 表示此為缺漏值 :
> n <- 1:50
> n
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
[25] 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
[49] 49 50
> n[25] #使用索引存取向量元素
[1] 25
R 輸出此向量時每 24 個元素為一列, 因此第二列第一個元素索引為 25, 第三列第一個元素索引為 49. 如果 ":" 冒號運算子前面數值比後面數值大, R 會自動偵測出此為遞減序列, 例如 :
> 9:0
[1] 9 8 7 6 5 4 3 2 1 0
R 提供內建函數 c() 來連接向量 (c 表示 combine 或 concat), 例如 :
> fibo <- c(0,1,1,2,3,5,8,13) #8 個費伯納西整數向量
> fibo
[1] 0 1 1 2 3 5 8 13
> fibo[4] #第 4 個元素為 2 (索引從 1 起算)
[1] 2
> users <- c("Tony","Peter","Kelly","Amy") #字串向量
> users
[1] "Tony" "Peter" "Kelly" "Amy"
> users[2] #第 2 個元素為 "Peter" (索引從 1 起算)
[1] "Peter"
users[5] #不存在的元素
[1] NA
[1] TRUE FALSE FALSE FALSE
> adult[1] #第 1 個元素為 TRUE (索引從 1 起算)
[1] TRUE
向量的索引可以用 ":" 運算子做範圍存取, 但不能向 Python 的串列那樣頭尾不指定時表示到頭或到尾, 例如 :
向量的索引可用負數排除指定元素, 例如 -2 表示排除索引 2 :
seq() 也可以產生實數向量, 例如 :
> seq(from=3.5,to=10.2) #by 預設為 1
[1] 3.5 4.5 5.5 6.5 7.5 8.5 9.5
> seq(from=-5,to=5,length=9) #9 個元素
[1] -5.00 -3.75 -2.50 -1.25 0.00 1.25 2.50 3.75 5.00
3. 使用 rep() 函數建立向量 :
R 還有一個重複函數 rep() 常用於產生向量物件, 以 help(rep) 查詢可知 rep() 除了要重複的向量當第一參數外, 主要有下面 3 個參數 :
> names <- c("花甲","雅婷", "阿瑋")
> rep(names) #預設重複 1 次
[1] "花甲" "雅婷" "阿瑋"
> rep(names, 3) #重複 3 次
[1] "花甲" "雅婷" "阿瑋" "花甲" "雅婷" "阿瑋" "花甲" "雅婷" "阿瑋"
> rep(names, length=3) #重複後向量長度為 3
[1] "花甲" "雅婷" "阿瑋"
> rep(names, length=5) #重複後向量長度為 5
[1] "花甲" "雅婷" "阿瑋" "花甲" "雅婷"
> rep(names, 2, 2) #重複 2 次, 但重複後向量長度為 2
[1] "花甲" "雅婷"
> rep(names, 2) #重複 2 次
[1] "花甲" "雅婷" "阿瑋" "花甲" "雅婷" "阿瑋"
> rep(names, 2, each=2) #整個向量重複 2 次, 重複時每個元素重複 2 次
[1] "花甲" "花甲" "雅婷" "雅婷" "阿瑋" "阿瑋" "花甲" "花甲" "雅婷" "雅婷"
[11] "阿瑋" "阿瑋"
> rep(names, 2, each=0) #重複次數須大於 0
character(0)
不過 each 參數只能以固定次數重複每個元素, 如果要指定各元素的重複次數該怎麼做? 這時可傳入整數向量的 times 參數來達成, 但要注意 times 向量元素個數須與被重複之向量元素個數相等, 否則會執行錯誤, 例如 :
> rep(c(4,5,6), c(1,2,3)) #參數 times 為向量
[1] 4 5 5 6 6 6
> rep(c("花甲","雅婷","阿瑋"), c(1,2,3)) #參數 times 為向量
[1] "花甲" "雅婷" "雅婷" "阿瑋" "阿瑋" "阿瑋"
> rep(1:5, 1:4) #參數 times 少一個元素
Error in rep(1:5, 1:4) : 'times' 引數不正確
> rep(1:5, 1:5) #參數 times 元素個數剛剛好
[1] 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5
> rep(1:5, 1:6) #參數 times 多一個元素
Error in rep(1:5, 1:6) : 'times' 引數不正確
R 語言對 6 種原型向量都提供了同名的函數來建立向量 :
函數 numeric(length) 會建立一個長度為 length, 值為 0 的實數向量 (double), 例如 :
> numeric(10) #建立一個含有 10 個元素的 0 向量
[1] 0 0 0 0 0 0 0 0 0 0
> (v=numeric(10)) # 外圍的 () 代表 print()
[1] 0 0 0 0 0 0 0 0 0 0
> v
[1] 0 0 0 0 0 0 0 0 0 0
> v[1] <- 1; v[7] <- 7; v[10] <- 10 #更改 0 向量元素值
> v
[1] 1 0 0 0 0 0 7 0 0 10
> v=numeric(10)
> class(v)
[1] "numeric"
> mode(v)
[1] "numeric"
> typeof(v)
[1] "double" #numerc() 建立的是 double 實數
函數 integer(length) 會建立一個長度為 length, 值為 0 的整數向量 (integer), 例如 :
> v=integer(10)
> class(v)
[1] "integer"
> mode(v)
[1] "numeric"
> typeof(v)
[1] "integer"
5. 使用 vector() 函數建立向量 :
函數 vector() 可建立指定資料類型 (預設 logical) 與長度 (預設 0) 之向量, 格式如下 :
vector(mode="logical", length = 0)
例如 :
> vector() #建立空向量 (預設 logical)
logical(0) #空的 logical 向量
> v=vector(mode="integer",length=5) #建立長度為 5 的整數向量
> v
[1] 0 0 0 0 0
> mode(v)
[1] "numeric" #模式 (mode) 為 numeric
> class(v) #類型 (class) 為 integer
[1] "integer"
> v=vector(mode="double",length=5) #建立長度為 5 的實數向量
> v
[1] 0 0 0 0 0
> class(v)
[1] "numeric" #模式 (mode) 為 numeric
> mode(v) #類型 (class) 為 numeric
[1] "numeric"
> v=vector(mode="double",length=10)
> v
[1] 0 0 0 0 0 0 0 0 0 0
> v[1] <- 1; v[7] <- 7; v[10] <- 10
> v
[1] 1 0 0 0 0 0 7 0 0 10
四. 運算子 :
R 語言基本資料型態為向量, 因此主要的運算也是向量運算, 其運算子如下 :
運算子優先順序如下 :
例如 :
> 3**2 #平方
[1] 9
> 3^2 #平方
[1] 9
> c(1,2,3,4,5)**2 #各分量都平方
[1] 1 4 9 16 25
> (1:10)**2 #各分量都平方
[1] 1 4 9 16 25 36 49 64 81 100
> 5e5/2e3 #科學表示法指數相除
[1] 250
> 1*2/3 #乘除依照順序計算 (先乘後除)
[1] 0.6666667
> 1/2*3 #乘除依照順序計算 (先除後乘)
[1] 1.5
五. 內建函數 :
R 語言內建很多好用函數, 因為 R 是向量語言, 這些函數的傳回值都是向量.
1. 向量建構函數 :
這些函數的用法已如上述.
2. 物件結構查詢函數 :
這些函數主要用來查詢資料物件之結構訊息, str() 用來檢查物件結構與內容, 例如 :
> str(1:10)
int [1:10] 1 2 3 4 5 6 7 8 9 10
> str(c(1.1, 2.2, 3.3))
num [1:3] 1.1 2.2 3.3
> str(c("A", "B", "C"))
chr [1:3] "A" "B" "C"
> str(c(TRUE, FALSE, T, F))
logi [1:4] TRUE FALSE TRUE FALSE
> str(c(1+1i, 2+2i))
cplx [1:2] 1+1i 2+2i
> str(raw(3))
raw [1:3] 00 00 00
> str(c(NA, NA))
logi [1:2] NA NA
> str(c(NA, NULL))
logi NA
length() 傳回向量的元素個數 :
> length(100)
[1] 1
> length(1:10)
[1] 10
> length(c("a","b","c"))
[1] 3
dim() 查詢物件的維度, 主要是用在矩陣, 陣列, 資料框等較複雜資料型態. 向量雖然看起來像是一維陣列, 但其實 R 語言的向量與因子類型是沒有維度的 (NULL), 例如 :
> dim(1:5) #向量沒有維度 (NULL)
NULL
> dim(matrix(1:10, 2))
[1] 2 5
> dim(array(1:10, 2))
[1] 2
> dim(array(1:24, c(3,4,2)))
[1] 3 4 2
> dim(factor(c("A","B","B","C"))) # factor 類型沒有維度 (NULL)
NULL
> name <- c("Kelly", "Peter", "Amy")
> gender <- c("Female", "Male", "Female")
> height <- c(162, 170, 161)
> dim(data.frame(name, gender, height))
[1] 3 3
四個檢查資料類型的函數 : class(), mode(), typeof(), storage.mode(), 傳回值差異不大, 其中 typeof() 與 storage.mode() 能區分出 integer 與 double; class() 可區分出 integer, 而 mode() 則通通視為 numeric, 例如 :
> class(1:5)
[1] "integer"
> mode(1:5)
[1] "numeric"
> typeof(1:5)
[1] "integer"
> storage.mode(1:5)
[1] "integer"
> class(c(3.14, 1.728))
[1] "numeric"
> mode(c(3.14, 1.728))
[1] "numeric"
> typeof(c(3.14, 1.728))
[1] "double"
> storage.mode(c(3.14, 1.728))
[1] "double"
> class(c(TRUE, FALSE))
[1] "logical"
> mode(c(TRUE, FALSE))
[1] "logical"
> typeof(c(TRUE, FALSE))
[1] "logical"
> storage.mode(c(TRUE, FALSE))
[1] "logical"
> class(c("A", "B", "C"))
[1] "character"
> mode(c("A", "B", "C"))
[1] "character"
> typeof(c("A", "B", "C"))
[1] "character"
> storage.mode(c("A", "B", "C"))
[1] "character"
> class(c(1+2i, 1-2i))
[1] "complex"
> mode(c(1+2i, 1-2i))
[1] "complex"
> typeof(c(1+2i, 1-2i))
[1] "complex"
> storage.mode(c(1+2i, 1-2i))
[1] "complex"
> class(vector(mode="raw"))
[1] "raw"
> mode(vector(mode="raw"))
[1] "raw"
> typeof(vector(mode="raw"))
[1] "raw"
> storage.mode(vector(mode="raw"))
[1] "raw"
輸出摘要如下表 :
3. 物件判斷函數 :
R 語言提供下列函數來判斷一個物件是否為某種資料類型 :
例如 :
> is.integer(c(1,2,3)) #R 的數值預設是 double
[1] FALSE
> typeof(c(1,2,3))
[1] "double"
> i=integer(3)
> i
[1] 0 0 0
> is.integer(i)
[1] TRUE
> is.numeric(i)
[1] TRUE
> d=double(3)
> d
[1] 0 0 0
> is.integer(d)
[1] FALSE
> is.numeric(d)
[1] TRUE
由於 R 語言的數值預設是 double, 因此 c(1,2,3) 是 double 類型的數值向量, 用 is.integer() 去檢驗會得到 FALSE, 必須用 integer() 建立的向量才是整數向量.
但若用 integer() 建立整數向量後, 卻填入浮點數, R 語言會自動將此向量轉型為 double, 例如 :
> i=integer(3) #建立有 3 元素之整數向量
> i
[1] 0 0 0
> i[1]=1.1 #整數向量填入實數
> i
[1] 1.1 0.0 0.0
> typeof(i) #自動轉型為實數向量
[1] "double"
4. 轉型函數 :
R 語言的每一種類型的資料物件都可以透過 as.xxx() 函數強制轉型 :
例如 :
> v <- c(1,2,3) #建立一個實數向量
> v
[1] 1 2 3
> class(v)
[1] "numeric"
> a <- as.integer(v) #強制轉型為整數向量
> a
[1] 1 2 3
> class(a)
[1] "integer"
> a <- as.character(v) #強制轉型為字元向量
> a
[1] "1" "2" "3"
> class(a)
[1] "character"
> a <- as.logical(v) #強制轉型為布林向量
> a
[1] TRUE TRUE TRUE
> class(a)
[1] "logical"
> a <- as.complex(v) #強制轉型為複數向量
> a
[1] 1+0i 2+0i 3+0i
> class(a)
[1] "complex"
> a <- as.raw(v) #強制轉型為原始數據向量
> a
[1] 01 02 03
> class(a)
[1] "raw"
> a <- as.array(v) #強制轉型為陣列物件
> a
[1] 1 2 3
> class(a)
[1] "array"
> a <- as.list(v) #強制轉型為列表物件
> a
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
> class(a)
[1] "list"
> a <- as.factor(v) #強制轉型為因子物件
> a
[1] 1 2 3
Levels: 1 2 3
> class(a)
[1] "factor"
> a <- as.matrix(v) #強制轉型為矩陣物件
> a
[,1]
[1,] 1
[2,] 2
[3,] 3
> class(a)
[1] "matrix"
> a <- as.data.frame(v) #強制轉型為資料框物件
> a
v
1 1
2 2
3 3
> class(a)
[1] "data.frame"
5. 排序函數 :
排序函數可對數值元素進行排序 :
注意, 這裡的秩 (rank) 並非矩陣中的秩, 而是原向量元素經 sort() 排序後的索引位置, 例如 :
> v=c(9,4,7,2,1,6,3)
> sort(v)
[1] 1 2 3 4 6 7 9 #由小至大排序
> v
[1] 9 4 7 2 1 6 3 #sort() 不會影響原向量
> rank(v) #若 sort() 則元素在原向量之索引
[1] 7 4 6 2 1 5 3
> rev(v) #由大至小排序
[1] 3 6 1 2 7 4 9
> v
[1] 9 4 7 2 1 6 3 #rev() 不會影響原向量
可見呼叫 sort() 或 rev() 並不會改變原向量, 而是傳回一個排序後的新向量. rank() 的傳回值顯示原向量第一個元素 9 排序後將位於索引 7; 第二個元素 4 位置在索引 4, ..., 因此 rank()
6. 數學函數 :
例如 :
指數與對數 :
[1] 3
> log10(10)
[1] 1
> log2(8)
[1] 3
> log10(100)
[1] 2
三角函數 :
> sin(30*pi/180)
[1] 0.5
> sin(45*pi/180)
[1] 0.7071068
> sqrt(2)/2
[1] 0.7071068
> sin(60*pi/180)
[1] 0.8660254
> sqrt(3)/2
[1] 0.8660254
> sin(90*pi/180)
[1] 1
> cos(30*pi/180)
[1] 0.8660254
> cos(45*pi/180)
[1] 0.7071068
> cos(60*pi/180)
[1] 0.5
> cos(90*pi/180)
[1] 6.123032e-17
7. 輸出函數 :
在 R Console 中輸入變數名稱或表達式後, R 會直接輸出其值. 事實上這是因為 R 自動呼叫了 print() 函數來顯示之故. R 語言提供 print() 與 cat() 兩個輸出顯示函數 :
print() 可以輸出任何 R 物件 (包括陣列, 列表, 矩陣等) 並予以格式化, 例如 :
> matrix(c(1,2,3,4,5,6),2,3)
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
> print(matrix(c(1,2,3,4,5,6),2,3))
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
但 print() 一次只能輸出一個物件, 若要同時輸出多個物件必須連續呼叫 print() :
> print("The square of 2 is ");sqrt(2)
[1] "The square of 2 is "
[1] 1.414214
因為 print() 預設會跳行, 因此分成兩行輸出. 但 cat() 則可串接多個物件, 例如 :
> cat("The square of 2 is",sqrt(2),"\n")
The square of 2 is 1.414214
參考 :
# Variable Name Restrictions in R
# R筆記–(2)基本資料型態
# R Variables and Constants
# Beginner's guide to R: Syntax quirks you'll want to know
不論是 "<-" 或 "=" 都可以用來同時賦值多個變數, 例如 :
> a <- b <- 2
> a
[1] 2
> b
[1] 2
> a = b = 2
> a
[1] 2
> b
[1] 2
合法的變數名稱範例如下 :
> name <- "tony"
> name
[1] "tony"
> .name <- "Tony"
> .name
[1] "Tony"
> p2p <- "peer to peer"
> p2p
[1] "peer to peer"
> .n_ame="tony" #小數點後面不是數字或底線可也
> .n_ame
[1] "tony"
> .n_ame="tony" #小數點後面不是數字或底線可也
> .n_ame
[1] "tony"
> IF=TRUE #IF 不是保留字可也
> IF
[1] TRUE
> 名字
[1] "Tony"
> assign("x",1)
> x
[1] 1
下面則是不合法的變數名稱 :
> if=TRUE #不可以使用保留字 if
錯誤: 未預期的 '=' in "if="
> NA="" #不可以使用保留字 NA
Error in NA = "" : (do_set) 賦值公式左側不正確
> .2name="tony" #小數點後面不可以是數字
錯誤: unexpected symbol in ".2name">._name="tony" #小數點後面不可以是底線
錯誤: unexpected input in "_"
另外, R 語言以跳行作為一個敘述結束標記, 若跳行時敘述不完整, 則會出現 "+" 符號表示繼續輸入未完部分. 若要在一行裡執行多個敘述, 則個敘述之間用分號 ";" 隔開即可, 例如 :
> v1 <- 1:10; v2 <- c("A", "B")
> v1
[1] 1 2 3 4 5 6 7 8 9 10
> v2
[1] "A" "B"
三. 資料型態 :
R 是物件導向語言, R 所有的東西不論是常數, 變數, 函數, 甚至表示式都是物件. R 常用的資料物件有下面幾種 :
- 向量 (vector)
- 矩陣 (matrix)
- 陣列 (array)
- 因子 (factor)
- 列表 (list)
- 資料框 (data.frame)
- 日期物件 (Date)
- 日期時間物件 (POSIXct/POSIXt)
> 5
[1] 5 #純量 5 在 R 中是單一元素的向量
> length(5) #查詢向量長度 (元素個數)
[1] 1
> 5[1] #索引 1 就是資料本身
[1] 5
> 5[2] #索引 2 無值=NA
[1] NA
R 的向量資料有如下 6 種類型, 稱為原型向量 (atomic vector), 此乃相對於被稱為泛型向量 (generic vector) 的列表 (list) 而言, 泛型向量例如 list 的元素允許異質, 亦即可以是任何資料物件 (vector, list, array, matrix, data.frame 等等), 但向量的元素必須是同質性資料 (即全部元素之資料型態必須相同) :
資料類型 | 說明 |
integer | 整數資料, 以 L 結尾, 例如 10L. |
numeric | 數值資料, 包含整數與倍精度實數 (預設), 可用浮點或科學記號形式. |
character | 字元資料, 使用單引號或雙引號夾住. |
logical | 布林資料, 只有 T (TRUE) 與 F (FALSE) 兩種值. |
complex | 複數資料, 即 a+bi 包含實部 a 與虛部 b 的複數 |
raw | 原始資料, 以二進位形式 |
注意, 類型 numeric 包含 integer 與 double 兩種數值, 預設是 double (實數), 可用浮點數如 3.14159 或科學記號 3.14159e1 表示. 向量可用 class(), typeof(), mode(), 或 storage.mode() 這四個內建函數查詢其類型. 其次, R 與數學習慣一樣使用小寫 i 來表示虛數, 這與 Python 偏向工程界使用 j 來表記虛數有所不同.
常數看似純量 (scaler), 但其實是只含有一個元素的向量, 例如在 R console 輸入數字或字串 :
> 5 #單一元素的向量 (整數)
[1] 5
> "Tony" #單一元素的向量 (字元)
[1] "Tony"
> 6.626069934e-34 #科學表示法 (普郎克常數)
[1] 6.62607e-34
> 6.626069934*10^-34 #指數表示法 (普郎克常數)
[1] 6.62607e-34
上面輸出訊息的每一列開頭會顯示該列第一個元素的索引, 常數向量 5 只含有一個元素 5, [1] 表示此輸出列第一個元素 5 在向量中的索引為 1.
向量是有序的同類型資料 (即不可文字與數字夾雜), 相當於是一維陣列, 其元素 (分量) 可以用索引存取, 例如向量 v 的第 i 個元素為 v[i]. 不過與 C 或 Python 等語言不同的是, R 的有序資料物件索引都是從 1 起始的, 不是 0.
在 R 語言大部分的向量含有多個分量 (元素), R 提供了多種方法來建立數值向量 :
[1] "Tony"
> 6.626069934e-34 #科學表示法 (普郎克常數)
[1] 6.62607e-34
> 6.626069934*10^-34 #指數表示法 (普郎克常數)
[1] 6.62607e-34
上面輸出訊息的每一列開頭會顯示該列第一個元素的索引, 常數向量 5 只含有一個元素 5, [1] 表示此輸出列第一個元素 5 在向量中的索引為 1.
向量是有序的同類型資料 (即不可文字與數字夾雜), 相當於是一維陣列, 其元素 (分量) 可以用索引存取, 例如向量 v 的第 i 個元素為 v[i]. 不過與 C 或 Python 等語言不同的是, R 的有序資料物件索引都是從 1 起始的, 不是 0.
在 R 語言大部分的向量含有多個分量 (元素), R 提供了多種方法來建立數值向量 :
- 冒號運算子
- seq() 函數
- rep() 函數
- integer(), numeric(), character(), logical(), complex(), raw() 函數
- vector() 函數
1. 使用冒號運算子建立向量 :
建立向量的第一個方法是利用冒號運算子來產生間隔為 1 的向量, 例如 1:50 表示含有元素 1~50 的整數向量, 例如 :
> 1:50
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
[25] 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
[49] 49 50
冒號運算子也可以用在浮點數, 間隔同樣是 1:
> 2.2:9.9
[1] 2.2 3.2 4.2 5.2 6.2 7.2 8.2 9.2
> 9.9:2.2
[1] 9.9 8.9 7.9 6.9 5.9 4.9 3.9 2.9
可以將向量指定給變數, 以索引來存取元素. 與 Python 或 C 語言族系不同的是, R 語言的索引是從 1 起算的, 若索引超出範圍將輸出 NA, 表示此為缺漏值 :
> n <- 1:50
> n
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
[25] 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
[49] 49 50
> n[25] #使用索引存取向量元素
[1] 25
> n[51] #不存在的索引其值為 NA
[1] NA
R 輸出此向量時每 24 個元素為一列, 因此第二列第一個元素索引為 25, 第三列第一個元素索引為 49. 如果 ":" 冒號運算子前面數值比後面數值大, R 會自動偵測出此為遞減序列, 例如 :
> 9:0
[1] 9 8 7 6 5 4 3 2 1 0
R 提供內建函數 c() 來連接向量 (c 表示 combine 或 concat), 例如 :
> fibo <- c(0,1,1,2,3,5,8,13) #8 個費伯納西整數向量
> fibo
[1] 0 1 1 2 3 5 8 13
[1] 2
> users <- c("Tony","Peter","Kelly","Amy") #字串向量
> users
[1] "Tony" "Peter" "Kelly" "Amy"
> users[2] #第 2 個元素為 "Peter" (索引從 1 起算)
[1] "Peter"
users[5] #不存在的元素
[1] NA
> adult <- c(TRUE,FALSE,FALSE,FALSE) #布林向量
> adult[1] TRUE FALSE FALSE FALSE
> adult[1] #第 1 個元素為 TRUE (索引從 1 起算)
[1] TRUE
向量的索引可以用 ":" 運算子做範圍存取, 但不能向 Python 的串列那樣頭尾不指定時表示到頭或到尾, 例如 :
> fibo[4:6]
[1] 2 3 5
> users[3:] #不支援
錯誤: 未預期的 ']' in "users[3:]"
> users[:4] #不支援
錯誤: 未預期的 ':' in "users[:"
> users[:4] #不支援
錯誤: 未預期的 ':' in "users[:"
> users[3:4]
[1] "Kelly" "Amy"
向量的索引可用負數排除指定元素, 例如 -2 表示排除索引 2 :
> users <- c("Tony","Peter","Kelly","Amy")
> users_1 <- users[-2] #排除索引 2
> users_1
[1] "Tony" "Kelly" "Amy"
也可以傳入真值向量來排除, 例如 :
> users <- c("Tony","Peter","Kelly","Amy")
> users[c(TRUE,FALSE,TRUE,TRUE)] #排除索引 2
[1] "Tony" "Kelly" "Amy"
連接函數 c() 可以連接不同類型的原型向量, 但串接後元素類型會改變, logical 與 numeric 串接 TRUE/FALSE 會變 1/0; logical 與 character 串接 TRUE/FALSE 會變 "TRUE"/"FALSE"; numerical 與 character 串接則全部變 character :
> fibo <- c(0,1,1,2,3,5,8,13)
> users <- c("Tony","Peter","Kelly","Amy")
> adult <- c(TRUE,FALSE,FALSE,FALSE)
comp <- c(1+1i,2+2i)
> c(adult,users)
[1] "TRUE" "FALSE" "FALSE" "FALSE" "Tony" "Peter" "Kelly" "Amy" #全部變字串
> c(fibo,users)
[1] "0" "1" "1" "2" "3" "5" "8" "13" "Tony"
[10] "Peter" "Kelly" "Amy"
> c(comp,fibo)
[1] 1+1i 2+2i 0+0i 1+0i 1+0i 2+0i 3+0i 5+0i 8+0i 13+0i #全部變複數
> c(comp,users)
[1] "1+1i" "2+2i" "Tony" "Peter" "Kelly" "Amy" #全部變字串
> c(comp,adult)
[1] 1+1i 2+2i 1+0i 0+0i 0+0i 0+0i #全部變複數
可見任何類型與字元向量串接全部會被轉型為字元, 數值, 布林值與複數串接全部被轉型為複數, 亦即 character 擁有最大的同化能力, complex 次之, numerical 又次之; 而 logical 則總是被同化, 其同化能力可以用下列關係表示 :
character > numerical > integer > logical
2. 使用 seq() 函數建立向量 :
建立向量的第二個方法是用 seq() 函數. 冒號 ":" 運算子只能產生間隔為 1 的向量, 若要產生規則間隔的數值序列可使用內建的 seq() 函數. 在 R console 輸入 help(seq) 可知 seq() 主要有 4 個參數 :
> seq(from=1,to=10,by=2) #1~10 的奇數
[1] 1 3 5 7 9
> seq(from=2,to=10,by=2) #2~10 的偶數
[1] 2 4 6 8 10
> seq(1,10,2) #不指明時預設參數為 to, from, by
[1] 1 3 5 7 9
> seq(from=-5,to=5,length=11) #11 個元素 (相當於 by=2)
[1] -5 -4 -3 -2 -1 0 1 2 3 4 5
> seq(from=-5,to=5,length=5) #元素長度 5 個
[1] -5.0 -2.5 0.0 2.5 5.0
> seq(from=5,to=-5,by=1) #倒序時 by 須為負數
Error in seq.default(from = 5, to = -5, by = 1) :
wrong sign in 'by' argument
> seq(from=5,to=-5,by=-1) #倒序時 by 須為負數
[1] 5 4 3 2 1 0 -1 -2 -3 -4 -5
> users <- c("Tony","Peter","Kelly","Amy")
> users[c(TRUE,FALSE,TRUE,TRUE)] #排除索引 2
[1] "Tony" "Kelly" "Amy"
連接函數 c() 可以連接不同類型的原型向量, 但串接後元素類型會改變, logical 與 numeric 串接 TRUE/FALSE 會變 1/0; logical 與 character 串接 TRUE/FALSE 會變 "TRUE"/"FALSE"; numerical 與 character 串接則全部變 character :
> fibo <- c(0,1,1,2,3,5,8,13)
> users <- c("Tony","Peter","Kelly","Amy")
> adult <- c(TRUE,FALSE,FALSE,FALSE)
comp <- c(1+1i,2+2i)
> c(adult,fibo)
[1] 1 0 0 0 0 1 1 2 3 5 8 13 #全部變整數> c(adult,users)
[1] "TRUE" "FALSE" "FALSE" "FALSE" "Tony" "Peter" "Kelly" "Amy" #全部變字串
> c(fibo,users)
[1] "0" "1" "1" "2" "3" "5" "8" "13" "Tony"
[10] "Peter" "Kelly" "Amy"
> c(comp,fibo)
[1] 1+1i 2+2i 0+0i 1+0i 1+0i 2+0i 3+0i 5+0i 8+0i 13+0i #全部變複數
> c(comp,users)
[1] "1+1i" "2+2i" "Tony" "Peter" "Kelly" "Amy" #全部變字串
> c(comp,adult)
[1] 1+1i 2+2i 1+0i 0+0i 0+0i 0+0i #全部變複數
可見任何類型與字元向量串接全部會被轉型為字元, 數值, 布林值與複數串接全部被轉型為複數, 亦即 character 擁有最大的同化能力, complex 次之, numerical 又次之; 而 logical 則總是被同化, 其同化能力可以用下列關係表示 :
character > numerical > integer > logical
2. 使用 seq() 函數建立向量 :
建立向量的第二個方法是用 seq() 函數. 冒號 ":" 運算子只能產生間隔為 1 的向量, 若要產生規則間隔的數值序列可使用內建的 seq() 函數. 在 R console 輸入 help(seq) 可知 seq() 主要有 4 個參數 :
- from : 起值
- to : 終值
- by : 增量值 (負為減量值)
- length 或 length.out : 元素個數
> seq(from=1,to=10,by=2) #1~10 的奇數
[1] 1 3 5 7 9
> seq(from=2,to=10,by=2) #2~10 的偶數
[1] 2 4 6 8 10
> seq(1,10,2) #不指明時預設參數為 to, from, by
[1] 1 3 5 7 9
> seq(from=-5,to=5) #by 預設值為 1
[1] -5 -4 -3 -2 -1 0 1 2 3 4 5> seq(from=-5,to=5,length=11) #11 個元素 (相當於 by=2)
[1] -5 -4 -3 -2 -1 0 1 2 3 4 5
> seq(from=-5,to=5,length=5) #元素長度 5 個
[1] -5.0 -2.5 0.0 2.5 5.0
> seq(from=5,to=-5,by=1) #倒序時 by 須為負數
Error in seq.default(from = 5, to = -5, by = 1) :
wrong sign in 'by' argument
> seq(from=5,to=-5,by=-1) #倒序時 by 須為負數
[1] 5 4 3 2 1 0 -1 -2 -3 -4 -5
seq() 也可以產生實數向量, 例如 :
> seq(from=3.5,to=10.2) #by 預設為 1
[1] 3.5 4.5 5.5 6.5 7.5 8.5 9.5
> seq(from=-5,to=5,length=9) #9 個元素
[1] -5.00 -3.75 -2.50 -1.25 0.00 1.25 2.50 3.75 5.00
3. 使用 rep() 函數建立向量 :
R 還有一個重複函數 rep() 常用於產生向量物件, 以 help(rep) 查詢可知 rep() 除了要重複的向量當第一參數外, 主要有下面 3 個參數 :
- times : 重複次數, 若不指明此為預設第二參數 (預設值為 1)
- length 或 length.out : 重複後之向量元素個數
- each : 每個元素重複次數 (each 須大於 0)
> names <- c("花甲","雅婷", "阿瑋")
> rep(names) #預設重複 1 次
[1] "花甲" "雅婷" "阿瑋"
> rep(names, 3) #重複 3 次
[1] "花甲" "雅婷" "阿瑋" "花甲" "雅婷" "阿瑋" "花甲" "雅婷" "阿瑋"
> rep(names, length=3) #重複後向量長度為 3
[1] "花甲" "雅婷" "阿瑋"
> rep(names, length=5) #重複後向量長度為 5
[1] "花甲" "雅婷" "阿瑋" "花甲" "雅婷"
> rep(names, 2, 2) #重複 2 次, 但重複後向量長度為 2
[1] "花甲" "雅婷"
> rep(names, 2) #重複 2 次
[1] "花甲" "雅婷" "阿瑋" "花甲" "雅婷" "阿瑋"
> rep(names, 2, each=2) #整個向量重複 2 次, 重複時每個元素重複 2 次
[1] "花甲" "花甲" "雅婷" "雅婷" "阿瑋" "阿瑋" "花甲" "花甲" "雅婷" "雅婷"
[11] "阿瑋" "阿瑋"
> rep(names, 2, each=0) #重複次數須大於 0
character(0)
不過 each 參數只能以固定次數重複每個元素, 如果要指定各元素的重複次數該怎麼做? 這時可傳入整數向量的 times 參數來達成, 但要注意 times 向量元素個數須與被重複之向量元素個數相等, 否則會執行錯誤, 例如 :
> rep(c(4,5,6), c(1,2,3)) #參數 times 為向量
[1] 4 5 5 6 6 6
> rep(c("花甲","雅婷","阿瑋"), c(1,2,3)) #參數 times 為向量
[1] "花甲" "雅婷" "雅婷" "阿瑋" "阿瑋" "阿瑋"
> rep(1:5, 1:4) #參數 times 少一個元素
Error in rep(1:5, 1:4) : 'times' 引數不正確
> rep(1:5, 1:5) #參數 times 元素個數剛剛好
[1] 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5
> rep(1:5, 1:6) #參數 times 多一個元素
Error in rep(1:5, 1:6) : 'times' 引數不正確
4. 使用原型向量函數建立向量 :
R 語言對 6 種原型向量都提供了同名的函數來建立向量 :
函數 | 說明 |
integer(length) | 建立長度為 length 的整數向量 |
double(length) | 建立長度為 length 的實數向量 |
numeric(length) | 建立長度為 length 的實數向量 |
character(length) | 建立長度為 length 的字元向量 |
logical(length) | 建立長度為 length 的布林向量 |
complex(length) | 建立長度為 length 的複數向量 |
raw(length) | 建立長度為 length 的 byte 向量 |
函數 numeric(length) 會建立一個長度為 length, 值為 0 的實數向量 (double), 例如 :
> numeric(10) #建立一個含有 10 個元素的 0 向量
[1] 0 0 0 0 0 0 0 0 0 0
> (v=numeric(10)) # 外圍的 () 代表 print()
[1] 0 0 0 0 0 0 0 0 0 0
> v
[1] 0 0 0 0 0 0 0 0 0 0
> v[1] <- 1; v[7] <- 7; v[10] <- 10 #更改 0 向量元素值
> v
[1] 1 0 0 0 0 0 7 0 0 10
> v=numeric(10)
> class(v)
[1] "numeric"
> mode(v)
[1] "numeric"
> typeof(v)
[1] "double" #numerc() 建立的是 double 實數
函數 integer(length) 會建立一個長度為 length, 值為 0 的整數向量 (integer), 例如 :
> v=integer(10)
> class(v)
[1] "integer"
> mode(v)
[1] "numeric"
> typeof(v)
[1] "integer"
5. 使用 vector() 函數建立向量 :
函數 vector() 可建立指定資料類型 (預設 logical) 與長度 (預設 0) 之向量, 格式如下 :
vector(mode="logical", length = 0)
例如 :
> vector() #建立空向量 (預設 logical)
logical(0) #空的 logical 向量
> v=vector(mode="integer",length=5) #建立長度為 5 的整數向量
> v
[1] 0 0 0 0 0
> mode(v)
[1] "numeric" #模式 (mode) 為 numeric
> class(v) #類型 (class) 為 integer
[1] "integer"
> v=vector(mode="double",length=5) #建立長度為 5 的實數向量
> v
[1] 0 0 0 0 0
> class(v)
[1] "numeric" #模式 (mode) 為 numeric
> mode(v) #類型 (class) 為 numeric
[1] "numeric"
> v=vector(mode="double",length=10)
> v
[1] 0 0 0 0 0 0 0 0 0 0
> v[1] <- 1; v[7] <- 7; v[10] <- 10
> v
[1] 1 0 0 0 0 0 7 0 0 10
四. 運算子 :
R 語言基本資料型態為向量, 因此主要的運算也是向量運算, 其運算子如下 :
運算子 | 說明 |
** | 平方 |
^ | 次方 |
+ - | 取正負 (單元運算) |
%/% | 整數除法取商 |
%% | 整數除法取餘數 |
* / + - | 四則運算 |
%*% | 矩陣乘法 |
運算子優先順序如下 :
- 指數 : 平方, 次方
- 乘, 除, 取商, 取餘數 : 依出現之先後次序
- 加, 減 : 依出現之先後次序
例如 :
> 3**2 #平方
[1] 9
> 3^2 #平方
[1] 9
> c(1,2,3,4,5)**2 #各分量都平方
[1] 1 4 9 16 25
> (1:10)**2 #各分量都平方
[1] 1 4 9 16 25 36 49 64 81 100
> 5e5/2e3 #科學表示法指數相除
[1] 250
> 1*2/3 #乘除依照順序計算 (先乘後除)
[1] 0.6666667
> 1/2*3 #乘除依照順序計算 (先除後乘)
[1] 1.5
五. 內建函數 :
R 語言內建很多好用函數, 因為 R 是向量語言, 這些函數的傳回值都是向量.
1. 向量建構函數 :
函數 | 說明 |
c(x1, x2, ...) | 將向量或純量組合成新的向量 |
seq(from, to, by, length) | 以起始值 from, 終值 to, 間隔 length 建立向量 |
rep(x, times) | 將向量 x 重複 times 次組合成新的向量 |
numeric(length) | 建立一個長度為 length 值為 0 的數值向量 |
vector(mode, length) | 建立類型 mode (預設 logical) 長度 length (預設 0) 之向量 |
2. 物件結構查詢函數 :
函數 | 說明 |
str(x) | 顯示物件結構與內容 |
length(x) | 計算向量長度 (即元素或分量個數) |
dim(x) | 顯示物件的因次 (dimension 維度) |
class(x) | 顯示物件類型 |
mode(x) | 顯示物件模式 |
typeof(x) | 顯示物件類型 |
storage.mode(x) | 顯示物件之儲存模式 |
這些函數主要用來查詢資料物件之結構訊息, str() 用來檢查物件結構與內容, 例如 :
> str(1:10)
int [1:10] 1 2 3 4 5 6 7 8 9 10
> str(c(1.1, 2.2, 3.3))
num [1:3] 1.1 2.2 3.3
> str(c("A", "B", "C"))
chr [1:3] "A" "B" "C"
> str(c(TRUE, FALSE, T, F))
logi [1:4] TRUE FALSE TRUE FALSE
> str(c(1+1i, 2+2i))
cplx [1:2] 1+1i 2+2i
> str(raw(3))
raw [1:3] 00 00 00
> str(c(NA, NA))
logi [1:2] NA NA
> str(c(NA, NULL))
logi NA
length() 傳回向量的元素個數 :
> length(100)
[1] 1
> length(1:10)
[1] 10
> length(c("a","b","c"))
[1] 3
dim() 查詢物件的維度, 主要是用在矩陣, 陣列, 資料框等較複雜資料型態. 向量雖然看起來像是一維陣列, 但其實 R 語言的向量與因子類型是沒有維度的 (NULL), 例如 :
> dim(1:5) #向量沒有維度 (NULL)
NULL
> dim(matrix(1:10, 2))
[1] 2 5
> dim(array(1:10, 2))
[1] 2
> dim(array(1:24, c(3,4,2)))
[1] 3 4 2
> dim(factor(c("A","B","B","C"))) # factor 類型沒有維度 (NULL)
NULL
> name <- c("Kelly", "Peter", "Amy")
> gender <- c("Female", "Male", "Female")
> height <- c(162, 170, 161)
> dim(data.frame(name, gender, height))
[1] 3 3
四個檢查資料類型的函數 : class(), mode(), typeof(), storage.mode(), 傳回值差異不大, 其中 typeof() 與 storage.mode() 能區分出 integer 與 double; class() 可區分出 integer, 而 mode() 則通通視為 numeric, 例如 :
> class(1:5)
[1] "integer"
> mode(1:5)
[1] "numeric"
> typeof(1:5)
[1] "integer"
> storage.mode(1:5)
[1] "integer"
> class(c(3.14, 1.728))
[1] "numeric"
> mode(c(3.14, 1.728))
[1] "numeric"
> typeof(c(3.14, 1.728))
[1] "double"
> storage.mode(c(3.14, 1.728))
[1] "double"
> class(c(TRUE, FALSE))
[1] "logical"
> mode(c(TRUE, FALSE))
[1] "logical"
> typeof(c(TRUE, FALSE))
[1] "logical"
> storage.mode(c(TRUE, FALSE))
[1] "logical"
> class(c("A", "B", "C"))
[1] "character"
> mode(c("A", "B", "C"))
[1] "character"
> typeof(c("A", "B", "C"))
[1] "character"
> storage.mode(c("A", "B", "C"))
[1] "character"
> class(c(1+2i, 1-2i))
[1] "complex"
> mode(c(1+2i, 1-2i))
[1] "complex"
> typeof(c(1+2i, 1-2i))
[1] "complex"
> storage.mode(c(1+2i, 1-2i))
[1] "complex"
> class(vector(mode="raw"))
[1] "raw"
> mode(vector(mode="raw"))
[1] "raw"
> typeof(vector(mode="raw"))
[1] "raw"
> storage.mode(vector(mode="raw"))
[1] "raw"
輸出摘要如下表 :
類型 | class() | mode() | typeof() | storage.mode() |
integer | integer | numeric | integer | integer |
numeric | numeric | numeric | double | double |
charactor | charactor | charactor | charactor | charactor |
logical | logica | logica | logica | logica |
complex | complex | complex | complex | complex |
raw | raw | raw | raw | raw |
3. 物件判斷函數 :
R 語言提供下列函數來判斷一個物件是否為某種資料類型 :
函數 | 說明 |
is.integer(x) | 判斷是否為整數向量 |
is.double(x) | 判斷是否為實數向量 |
is.numeric(x) | 判斷是否為數值向量 |
is.character(x) | 判斷是否為字元向量 |
is.logical(x) | 判斷是否為布林向量 |
is.complex(x) | 判斷是否為複數向量 |
is.raw(x) | 判斷是否為原始數據向量 |
is.array(x) | 判斷是否為陣列物件 |
is.list(x) | 判斷是否為列表物件 |
is.factor(x) | 判斷是否為因子物件 |
is.matrix(x) | 判斷是否為矩陣物件 |
is.data.frame(x) | 判斷是否為資料框物件 |
例如 :
> is.integer(c(1,2,3)) #R 的數值預設是 double
[1] FALSE
> typeof(c(1,2,3))
[1] "double"
> i=integer(3)
> i
[1] 0 0 0
> is.integer(i)
[1] TRUE
> is.numeric(i)
[1] TRUE
> d=double(3)
> d
[1] 0 0 0
> is.integer(d)
[1] FALSE
> is.numeric(d)
[1] TRUE
由於 R 語言的數值預設是 double, 因此 c(1,2,3) 是 double 類型的數值向量, 用 is.integer() 去檢驗會得到 FALSE, 必須用 integer() 建立的向量才是整數向量.
但若用 integer() 建立整數向量後, 卻填入浮點數, R 語言會自動將此向量轉型為 double, 例如 :
> i=integer(3) #建立有 3 元素之整數向量
> i
[1] 0 0 0
> i[1]=1.1 #整數向量填入實數
> i
[1] 1.1 0.0 0.0
> typeof(i) #自動轉型為實數向量
[1] "double"
4. 轉型函數 :
R 語言的每一種類型的資料物件都可以透過 as.xxx() 函數強制轉型 :
函數 | 說明 |
as.integer(x) | 判斷是否為整數向量 |
as.double(x) | 判斷是否為實數向量 |
as.numeric(x) | 判斷是否為數值向量 |
as.character(x) | 判斷是否為字元向量 |
as.logical(x) | 判斷是否為布林向量 |
as.complex(x) | 判斷是否為複數向量 |
as.raw(x) | 判斷是否為原始數據向量 |
as.array(x) | 判斷是否為陣列物件 |
as.list(x) | 判斷是否為列表物件 |
as.factor(x) | 判斷是否為因子物件 |
as.matrix(x) | 判斷是否為矩陣物件 |
as.data.frame(x) | 判斷是否為資料框物件 |
例如 :
> v <- c(1,2,3) #建立一個實數向量
> v
[1] 1 2 3
> class(v)
[1] "numeric"
> a <- as.integer(v) #強制轉型為整數向量
> a
[1] 1 2 3
> class(a)
[1] "integer"
> a <- as.character(v) #強制轉型為字元向量
> a
[1] "1" "2" "3"
> class(a)
[1] "character"
> a <- as.logical(v) #強制轉型為布林向量
> a
[1] TRUE TRUE TRUE
> class(a)
[1] "logical"
> a <- as.complex(v) #強制轉型為複數向量
> a
[1] 1+0i 2+0i 3+0i
> class(a)
[1] "complex"
> a <- as.raw(v) #強制轉型為原始數據向量
> a
[1] 01 02 03
> class(a)
[1] "raw"
> a <- as.array(v) #強制轉型為陣列物件
> a
[1] 1 2 3
> class(a)
[1] "array"
> a <- as.list(v) #強制轉型為列表物件
> a
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
> class(a)
[1] "list"
> a <- as.factor(v) #強制轉型為因子物件
> a
[1] 1 2 3
Levels: 1 2 3
> class(a)
[1] "factor"
> a <- as.matrix(v) #強制轉型為矩陣物件
> a
[,1]
[1,] 1
[2,] 2
[3,] 3
> class(a)
[1] "matrix"
> a <- as.data.frame(v) #強制轉型為資料框物件
> a
v
1 1
2 2
3 3
> class(a)
[1] "data.frame"
5. 排序函數 :
排序函數可對數值元素進行排序 :
函數 | 說明 |
sort(x) | 將向量元素由小至大排序 |
rev(x) | 將向量元素由大至小排序 |
rank(x) | 顯示向量的秩 (即原向量之元素排序後之索引位置) |
注意, 這裡的秩 (rank) 並非矩陣中的秩, 而是原向量元素經 sort() 排序後的索引位置, 例如 :
> v=c(9,4,7,2,1,6,3)
> sort(v)
[1] 1 2 3 4 6 7 9 #由小至大排序
> v
[1] 9 4 7 2 1 6 3 #sort() 不會影響原向量
> rank(v) #若 sort() 則元素在原向量之索引
[1] 7 4 6 2 1 5 3
> rev(v) #由大至小排序
[1] 3 6 1 2 7 4 9
> v
[1] 9 4 7 2 1 6 3 #rev() 不會影響原向量
6. 數學函數 :
函數 | 說明 |
c(x1, x2, ...) | 將向量或純量組合成新的向量 |
seq(from, to, by, length) | 以起始值 from, 終值 to, 間隔 length 建立向量 |
rep(x, times) | 將向量 x 重複 times 次組合成新的向量 |
numeric(length) | 建立一個長度為 length 值為 0 的數值向量 |
length(x) | 計算向量長度 (即元素或分量個數) |
range(x) | 查詢數值向量元素範圍 |
range(x1, x2, ...) | 查詢全部數值向量之元素範圍 |
sum(x) | 計算數值向量之元素和 |
sum(x1, x2, ...) | 計算全部數值向量之元素和 |
cumsum(x) | 計算數值向量各分量的累積和 |
prod(x) | 計算數值向量各分量的乘積 |
prod(x1, x2, ...) | 計算全部數值向量各分量的乘積 |
cumprod(x) | 計算全部數值向量各分量的累積乘積 |
round(x, digits=0) | 將數值向量各分量四捨五入至指定位數 |
ceiling(x) | 求大於等於各分量之最小整數 |
floor(x) | 求小於等於各分量之最大整數 |
trunc(x) | 將數值向量各分量無條件捨去 |
signif(x, digits=6) | 將數值向量各分量由左到右四捨五入至指定位數 |
min(x) | 求數值向量各分量之最小值 |
min(x1, x2, ...) | 求全部數值向量各分量的最小值 |
pmin(x1, x2, ...) | 求全部數值向量各對應分量的最小值 |
cummin(x) | 求數值向量各分量累積最小值 |
max(x) | 求數值向量各分量之最大值 |
max(x1, x2, ...) | 求全部數值向量各分量的最大值 |
pmax(x1, x2, ...) | 求全部數值向量各對應分量的最大值 |
cummax(x) | 求數值向量各分量累積最大值 |
abs(x) | 求數值向量各分量之絕對值 |
sqrt(x) | 求數值向量各分量之平方根 |
log(x) | 求數值向量各分量之自然對數 |
log2(x) | 求數值向量各分量以 2 為底之對數 |
log10(x) | 求數值向量各分量以 10 為底之對數 |
exp(x) | 求數值向量各分量之自然指數 |
sin(x) | 求數值向量各分量之正弦 |
cos(x) | 求數值向量各分量之餘弦 |
tan(x) | 求數值向量各分量之正切 |
asin(x) | 求數值向量各分量之反正弦 |
acos(x) | 求數值向量各分量之反餘弦 |
atan(x) | 求數值向量各分量之反正切 |
mean(x) | 求數值向量各分量之平均值 |
sd(x) | 求數值向量各分量之標準差 |
var(x) | 求數值向量各分量之變異數 |
median(x) | 求數值向量各分量之正弦中位數 |
factorial(x) | 階乘函數=x*(x-1)*(x-2)*....*3*2*1 |
例如 :
四捨五入函數 :
R 的四捨五入函數有兩個 :
- round(x, digits=0)
- signif(x, digits=6)
round() 的第二參數 digits 預設是 0, 可為正整數或負整數, 正整數時表示要四捨五入到小數點後第幾位, 例如 :
> round(1.23456789) #預設四捨五入到個位數
[1] 1
> round(1.23456789,1) #四捨五入到小數點後第 1 位
[1] 1.2
> round(1.23456789,2)
[1] 1.23
> round(1.23456789,3)
[1] 1.235
> round(1.23456789,4)
[1] 1.2346
> round(12345.6789)
[1] 12346
> round(12345.6789, 1)
[1] 12345.7
> round(12345.6789, 2)
[1] 12345.68
> round(12345.6789, 3)
[1] 12345.68 #奇怪, 不是應該 12345.679 嗎?
當 digits 為負整數時, -1 表示要四捨五入到十位; -2 表示要四捨五入到百位; -3 表示要四捨五入到千位, ... 例如 :
> round(12345.6789,-1) #四捨五入到十位數
[1] 12350
> round(12345.6789,-2) #四捨五入到百位數
[1] 12300
> round(12345.6789,-3) #四捨五入到千位數
[1] 12000
signif() 函數的 digits 參數表示由左到右的有效位數, 將下一位數四捨五入到有效位數的最後一位, 例如 :
> signif(12345.6789) #預設有效位數 6 位, 7 四捨五入至 6, 6 進一為 7
[1] 12345.7
> signif(12345.6789, digits=1) #有效位數 1 位, 2 四捨五入
[1] 10000
> signif(12345.6789, digits=2) #有效位數 2 位, 3 四捨五入
[1] 12000
> signif(12345.6789, digits=3) #有效位數 3 位, 4 四捨五入
[1] 12300
> signif(12345.6789, digits=4) #有效位數 4 位, 5 四捨五入, 4 進一為 5
[1] 12350
> signif(12345.6789, digits=5) #有效位數 5 位, 6 四捨五入, 5 進一為 6
[1] 12346
> signif(12345.6789, digits=6) #有效位數 6 位, 7 四捨五入, 6 進一為 7
[1] 12345.7
> signif(12345.6789, digits=7) #有效位數 7 位, 8 四捨五入, 7 進一為 8
[1] 12345.68
> signif(12345.6789, digits=8) #?
[1] 12345.68
> signif(12345.6789, digits=9) #?
[1] 12345.68
近似函數 :
R 的近似函數有 3 個 :
- ceiling(x) : 小於等於 x 的最大整數
- floor(x) : 大於等於 x 的最小整數
- trunc(x) : 無條件捨去至個位數
例如 :
> ceiling(123.4)
[1] 124
> ceiling(123.9)
[1] 124
> ceiling(-123.9)
[1] -123
> floor(123.9)
[1] 123
> floor(-123.9)
[1] -124
> trunc(123.9)
[1] 123
> trunc(-123.9)
[1] -123
[1] 3
> log10(10)
[1] 1
> log2(8)
[1] 3
> log10(100)
[1] 2
三角函數 :
> sin(30*pi/180)
[1] 0.5
> sin(45*pi/180)
[1] 0.7071068
> sqrt(2)/2
[1] 0.7071068
> sin(60*pi/180)
[1] 0.8660254
> sqrt(3)/2
[1] 0.8660254
> sin(90*pi/180)
[1] 1
> cos(30*pi/180)
[1] 0.8660254
> cos(45*pi/180)
[1] 0.7071068
> cos(60*pi/180)
[1] 0.5
> cos(90*pi/180)
[1] 6.123032e-17
7. 輸出函數 :
在 R Console 中輸入變數名稱或表達式後, R 會直接輸出其值. 事實上這是因為 R 自動呼叫了 print() 函數來顯示之故. R 語言提供 print() 與 cat() 兩個輸出顯示函數 :
函數 | 說明 |
print() | 輸出一個物件內容 (一次只能一個, 會自動跳行) |
cat() | 串接輸出多個向量物件 (不包含 list, matrix 等複合物件, 不會自動跳行) |
print() 可以輸出任何 R 物件 (包括陣列, 列表, 矩陣等) 並予以格式化, 例如 :
> matrix(c(1,2,3,4,5,6),2,3)
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
> print(matrix(c(1,2,3,4,5,6),2,3))
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
但 print() 一次只能輸出一個物件, 若要同時輸出多個物件必須連續呼叫 print() :
> print("The square of 2 is ");sqrt(2)
[1] "The square of 2 is "
[1] 1.414214
因為 print() 預設會跳行, 因此分成兩行輸出. 但 cat() 則可串接多個物件, 例如 :
> cat("The square of 2 is",sqrt(2),"\n")
The square of 2 is 1.414214
參考 :
# Variable Name Restrictions in R
# R筆記–(2)基本資料型態
# R Variables and Constants
# Beginner's guide to R: Syntax quirks you'll want to know
沒有留言:
張貼留言