要熟悉一個程式語言,第一步就是先了解定義在裡面的資料型態。而在R語言的資料型態,常用的有這些:
integer
number
logic
character
factor
vector
list
matrix
data frame
看起來很多感覺很複雜,但不用擔心,接下來會一邊用例子、一邊介紹這些型態。
這四個型態比較簡單:
integer
number
logic
character
若要在R裡宣告一個數字,可以這麼做:
a <- 3
b <- 1.6
在這裡,我們稱a
和b
為「變數」(或是物件)。
而<-
符號,會把右邊的東西,儲存到左邊的名字裡,使左邊的名字變成「變數」(如下圖)
當賦值結束後,我們會需要確認變數的資料型態,這時候可以使用str()
函式:
str(a)
## num 3
上面結果顯示,a
的資料型態是「number」,而非integer
。有點奇怪,對吧?
這是因為R預設的數字型態是「number」,意思是,若直接把數字存到變數中,其資料型態是「number」。 那麼,如果想要轉換資料型態,變成integer
呢?這時候就可以使用as.integer()
函式:
a <- as.integer(3)
str(a)
## int 3
如果,想要轉換成number
的資料型態呢? 應該猜到了,沒錯,就是使用as.numeric()
的函示。(不是number
,而是numeric
哦!)
更棒的是,這樣的概念可以「舉一反三」!下表就是各種資料型態,所對應的轉換函式:
資料型態 | 轉換函式 |
---|---|
integer | as.integer() |
number | as.numeric() |
character | as.character() |
factor | as.factor() |
matrix | as.matrix() |
vector | as.vector() |
list | as.list() |
data frame | as.data.frame() |
有時候,我們要確認變數的資料型態,是否為integer
,這時可以使用is.integer()
函式:
is.integer(a)
is.integer(b)
## [1] TRUE
## [1] FALSE
str()
的功能是「顯示資料型態」,而is.integer()
則是「判斷是否為integer,回傳TRUE/FALSE」。
當然,這時聰明的人就會思考,是不是也可以舉一反三呢?
答案是,可以的:
資料型態 | 判斷函式 |
---|---|
integer | is.integer() |
number | is.numeric() |
character | is.character() |
factor | is.factor() |
matrix | is.matrix() |
vector | is.vector() |
list | is.list() |
data frame | is.data.frame() |
所謂的布林代數(boolean),代表的是True
和False
,常用於邏輯式上的判斷。而在R裡面,以logic
的資料型態來表示:
a <- TRUE
b <- FALSE
str(a) #確認a的型態
is.integer(b) #判斷b是不是整數,但b是logic型態,所以回傳FALSE
## logi TRUE
## [1] FALSE
要定義一個character
變數的話,注意放在右邊的值,要用雙引號(" "
)括起來:
professor <- "Dr.Lee"
如果沒有括起來,右邊就會視為「變數」。若沒有事先定義的話,就會跳出錯誤訊息:
professor <- Dr.Lee
## Error in eval(expr, envir, enclos): 找不到物件 'Dr.Lee'
換句話說,只要事先定義好變數,那麼變數之間,就可以互相傳遞自己儲存的值:
a <- "Dr.Lee" # a的資料型態是character
professor <- a # a是變數,把a存到professor裡
str(professor) # 確認professor資料型態
## chr "Dr.Lee"
R裡面有一個十分重要的資料型態,那就是vector(陣列/向量)!
我們在資料分析時,常常是針對一張表(table/sheet)進行處理。有時候會需要處理「某一列」(row),或「某一行」(column),而這樣長長的一個row/column,在R裡就被儲存成vector的形式。
要定義一個vector,需要使用c()
的函式:
a <- c(5,10,15,20,25) # 建立一個number vector
b <- c("Tom", "Henry", "John") # 建立一個character vector
a
b
## [1] 5 10 15 20 25
## [1] "Tom" "Henry" "John"
在上面,定義一個vector變數叫做a,裡面的數字(1~5)就被稱為元素(element)。
vector
的概念其實不難懂,就把它想像成一條長長的火車,每個車廂都存放一個貨品(element)。
既然是車廂,那就一定有車廂編號,這在vector
裡面稱為index,表示方式為object[index]
。(如下圖)
(小練習)利用index,取出特定的element吧:
a[3] # Ans: 15 (取第3個element)
a[1:3] # Ans: 5 10 15 (取第1~第3個element)
a[c(2,4)] # Ans: 10 20 (取第2和第4個element)
在vector裡有一個需要注意的規則:「每一個element」都會是相同的型態!
a <- c(1, "john", 3) # 若是把number和character同時放入vector裡,
a # R會自動將所有element的型態,轉變成character
## [1] "1" "john" "3"
b <- c(T, 3, F) # logic和number在vector裡的話
b # T和F會被自動轉換成1和0,變成數字的vector
## [1] 1 3 0
當然,vector之間也可以進行數學運算:
a <- c(7,8,6,9,5) # 建立一個number vector
b <- c(2,4,6,0,1) # 建立一個number vector
a * b # a和b的第一個element相乘,第二個element相乘......
b^3 # 對b之中的每一個element三次方
b > 3 # 判斷b之中的哪些值大於 3 ,然後回傳 TRUE/FALSE
## [1] 14 32 36 0 5
## [1] 8 64 216 0 1
## [1] FALSE TRUE TRUE FALSE FALSE
factor
的型態,主要用來表示「類別變數」(category variable)。
(例如:性別(男、女),年級(小一、小二….碩一、碩二),地區(北、中、南、東)…等等。)
在用R進行資料分析時,當遇到這類「類別變數」時,要轉換成factor
的資料型態,再丟入模型(model)進行分析。
factor
的資料型態和vector
很相似,差別在於factor
具有額外的類別屬性(Levels)。
要建立factor的變數,可以使用factor()
函式:
gender <- c("boy", "girl", "boy", "boy", "girl") # 建立一個character vector
gender <- factor(gender) # 轉換成factor型態
gender # Levels的屬性代表: 在這個變數裡面,存在哪些類別
## [1] boy girl boy boy girl
## Levels: boy girl
如果有一組類別變數,要查看裡面存在著哪些類別,可以用levels()
函式:
levels(gender)
## [1] "boy" "girl"
還記得vector裡面,每一個element要相同型態的規定嗎?
但有時候,我們會想要把不同資料型態的值,放到同一個變數裡面,那這時又該怎麼辦?
在R裡面,有一種資料型態能解決這樣的問題,那就是列表(list
)。
舉個例子:一個人身上其實具備了許多資訊(性別,年齡,嗜好…),可是這些資訊的型態不盡相同。因此,若我們想要儲存「一個人的所有資訊」,那就可以用list
的資料型態(使用list()
函式):
Dr.Lee <- list(gender="man", age=18, hobby=c("tease", "be teased"))
Dr.Lee # list長什麼模樣呢~
## $gender
## [1] "man"
##
## $age
## [1] 18
##
## $hobby
## [1] "tease" "be teased"
str(Dr.Lee) # 看一下list裡面的資訊~
## List of 3
## $ gender: chr "man"
## $ age : num 18
## $ hobby : chr [1:2] "tease" "be teased"
你可能已經注意到hobby這個變數。沒錯,list可以存放「任何型態」的變數,自然也包括vector。(當然也包括list)
既然可以儲存資料,那也要可以把資料取出來才對!
R裡面有一個神奇的符號$
,用來取出特定的資料:
Dr.Lee$hobby # Dr.Lee的嗜好
Dr.Lee$age # Dr.Lee的年紀
## [1] "tease" "be teased"
## [1] 18
Dr.Lee[[3]] # 當然,也可以用index的方式
## [1] "tease" "be teased"
Dr.Lee[3] # 然而,上面那行有兩個中括號,這行卻只有一個,看看結果有什麼不同吧!
## $hobby
## [1] "tease" "be teased"
(小練習)試試看用str()
,比較看看在list中,用“一個中括號:和”兩個中括號“,取出來的資料型態有什麼差別吧!
str(Dr.Lee[[3]] ) # Ans:使用兩個中括號,取出來的資料是vector
str(Dr.Lee[3] ) # Ans:使用一個中括號,取出來的資料是list
之所以會把matrix
和data frame
在一起,是因為它們有很多觀念都很相似,使用的手法也幾乎雷同。
R裡面定義矩陣的方式很簡單,就是用matrix()
函式:
a <- matrix(c(1:6), nrow=3, ncol=2) #建立一個3x2的矩陣,依照column分別填入1~6的值
a
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
b <- matrix(c(3:8), nrow=2, ncol=3) #建立一個2x3的矩陣,依照column分別填入3~8的值
b
## [,1] [,2] [,3]
## [1,] 3 5 7
## [2,] 4 6 8
如果我要查看a裡面,(2,2)所對應的值是什麼,可以這麼做:
a[2,2]
## [1] 5
當然,也可以查看b的「第一列」裡所有值:
b[1, ] # 欄"空白"
## [1] 3 5 7
矩陣相乘的符號是`%*%``:
a %*% b #矩陣相乘
## [,1] [,2] [,3]
## [1,] 19 29 39
## [2,] 26 40 54
## [3,] 33 51 69
和矩陣相關的運算函式:
(小練習)試試看這些函式的作用:
#建立一個3x2的矩陣,隨機從1~100內填入6個值
a <- matrix(sample(1:100, size=6), nrow=3, ncol=2)
#建立一個2x3的矩陣,隨機從1~100內填入6個值
b <- matrix(sample(1:100, size=6), nrow=2, ncol=3)
#建立一個4x4的方陣,隨機從1~100內填入16個值
c <- matrix(sample(1:100, size=16), nrow=4, ncol=4)
t(a) #轉置
diag(b) #對角矩陣
det(c) #計算行列式值
solve(c) #反矩陣
毫無疑問的,這是R語言裡最特別的功能之一:data frame!
平常我們在分析資料,多半是使用Excel,打開裡面的Sheet,然後進行統計分析或計算。
如果說,Excel對應的東西是Sheet,那R所對應的就是data frame。
以下直接拿一個資料進行介紹。
下載資料後,用Excel打開就會像這樣:
現在來把這個csv檔,匯入到R裡面,變成一個data frame:
首先,找到右邊的「Import Dataset」,選取「From Text File」
去找剛剛下載的csv檔,選取之後會跳出這個畫面,點「Import」
這樣就成功把資料匯入到R裡面,狀態就會像下圖一樣:
讓我們用str()
查看這個資料,會發現資料型態為data frame,以及詳列出每一個變數的資訊:
str(Payment_and_value_of_care_._Hospital)
## 'data.frame': 14301 obs. of 23 variables:
## $ Provider.ID : Factor w/ 4767 levels "010001","010005",..: 98 98 98 101 101 101 102 102 102 104 ...
## $ Hospital.name : Factor w/ 4572 levels " HIMA SAN PABLO BAYAMON",..: 612 612 612 3154 3154 3154 3146 3146 3146 2999 ...
## $ Address : Factor w/ 4740 levels " CALLE CONCEPCION VERA AYALA #550 S",..: 2056 2056 2056 4705 4705 4705 2967 2967 2967 2 ...
## $ City : Factor w/ 2891 levels "ABBEVILLE","ABERDEEN",..: 2403 2403 2403 2640 2640 2640 2346 2346 2346 1998 ...
## $ State : Factor w/ 55 levels "AK","AL","AR",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ ZIP.Code : int 99669 99669 99669 99686 99686 99686 99664 99664 99664 99833 ...
## $ County.name : Factor w/ 1530 levels "","ABBEVILLE",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ Phone.number : num 9.07e+09 9.07e+09 9.07e+09 9.08e+09 9.08e+09 ...
## $ Payment.measure.name : Factor w/ 3 levels "Payment for heart attack patients",..: 1 2 3 1 2 3 1 2 3 1 ...
## $ Payment.measure.ID : Factor w/ 3 levels "PAYM_30_AMI",..: 1 2 3 1 2 3 1 2 3 1 ...
## $ Payment.category : Factor w/ 5 levels "Greater than the National Average Payment",..: 5 3 3 5 5 5 5 5 5 5 ...
## $ Denominator : Factor w/ 924 levels "1,001","1,002",..: 924 665 917 924 924 924 924 924 924 924 ...
## $ Payment : Factor w/ 6157 levels "","$10045.00",..: 1 990 576 1 1 1 1 1 1 1 ...
## $ Lower.estimate : Factor w/ 6194 levels "$10,011","$10,013",..: 6194 723 520 6194 6194 6194 6194 6194 6194 6194 ...
## $ Higher.estimate : Factor w/ 6313 levels "$10,269","$11,359",..: 6313 1532 599 6313 6313 6313 6313 6313 6313 6313 ...
## $ Payment.footnote : Factor w/ 4 levels "","1 - The number of cases/patients is too few to report.",..: 2 1 1 2 2 2 2 2 2 2 ...
## $ Value.of.care.display.name: Factor w/ 4 levels "","Value of Care Heart Attack measure",..: 2 3 4 2 3 4 2 3 4 2 ...
## $ Value.of.care.display.ID : Factor w/ 4 levels "","MORT_PAYM_30_AMI",..: 2 3 4 2 3 4 2 3 4 2 ...
## $ Value.of.care.category : Factor w/ 11 levels "","Average mortality and average payment",..: 8 2 2 8 8 8 8 8 8 8 ...
## $ Value.of.care.footnote : Factor w/ 3 levels "","13 - Results cannot be calculated for this reporting period.",..: 2 1 1 2 2 2 2 2 2 2 ...
## $ Measure.start.date : Factor w/ 1 level "07/01/2011": 1 1 1 1 1 1 1 1 1 1 ...
## $ Measure.End.Date : Factor w/ 1 level "06/30/2014": 1 1 1 1 1 1 1 1 1 1 ...
## $ Location : Factor w/ 4767 levels "#1 MEDICAL PARK DRIVE\nBENTON, AR 72015\n(34.572716, -92.585094)",..: 2074 2074 2074 4731 4731 4731 2986 2986 2986 4732 ...
又或者,可以利用data.frame()
函式,創造自己的data frame:
tmp <- data.frame(Student_ID=c(1,2,3,4,5),
name=c("Helen", "Lun", "Leon", "Kevin", "Tommy"),
score=c(80,36, 88.9, 97.5, 60))
tmp # data frame的型態
## Student_ID name score
## 1 1 Helen 80.0
## 2 2 Lun 36.0
## 3 3 Leon 88.9
## 4 4 Kevin 97.5
## 5 5 Tommy 60.0
data frame裡有一些好用的手法,可以有效地協助我們達成目的。
首先,先來一段程式碼:
tmp[4,3]
## [1] 97.5
這裡所代表的意思是:
有沒有和矩陣很像?
因此,如果我們要看第一人的分數(第一列):
tmp[1, ] # 在欄的地方"空白"
## Student_ID name score
## 1 1 Helen 80
又或者,我們要看所有人的分數(第三欄):
tmp[, 3] # 在列的地方"空白"
## [1] 80.0 36.0 88.9 97.5 60.0
除此之外,還記得R裡面有個神奇符號$
嗎?
在data frame裡面,$
可以用來指定「欄位名稱」,擷取該欄位的所有值:
tmp$name #查看所有人的名字
## [1] Helen Lun Leon Kevin Tommy
## Levels: Helen Kevin Leon Lun Tommy
但有時候我們會想要特定的資訊(例如“Leon”這個人的資訊),那這時可以這麼做:
tmp[tmp$name == "Leon", ]
## Student_ID name score
## 3 3 Leon 88.9
以上包含了兩個步驟:我們先看tmp$name == "Leon"
的結果:
tmp$name == "Leon"
## [1] FALSE FALSE TRUE FALSE FALSE
tmp$name == "Leon"
這行指令,表示會去判斷所有人的名字(tmp$name)裡,是否有符合“Leon”的資料。如果有的話,回傳TRUE,不然就是FALSE。
第二步,把這行條件式放到data frame的「列」中,是TRUE的「那一列資料」就會顯示出來。
換句話說,原本的這行程式碼tmp[tmp$name == "Leon", ]
,其實同等於下面這行程式碼:
tmp[c(FALSE, FALSE, TRUE, FALSE, FALSE), ]
## Student_ID name score
## 3 3 Leon 88.9
在R裡面,比較嶄新而且實用的資料型態,就是vector
,list
以及data frame
。以經驗來說,在資料處理/分析的過程中,若是能好好運用這三種資料型態,可以達到事半功倍的效果。
除此之外,這篇文章有提到一些實用的函式,接下來會介紹更多常見的函式,包括:常見的函式、如何去下載想要的函式,如何去理解函式的狀態…等等。
It’s still a long way to go~
雖然在R中進行賦值時,除了使用符號<-
以外,也可以使用=
。
但是在R的官方文件,又或者是Google’s R Style Guide中,都強調最好不要使用=
,因為有時候會造成問題。
有興趣的話,可以參考以上連結,更進一步的了解。