8 精簡的變數型別
8.1 暸解不同的變數型別
變數型別 | 變數型別英文 | 範例 |
---|---|---|
數值 | numeric | 2 |
整數 | integer | 2L |
邏輯值 | logical | TRUE |
文字 | character | “Learning R the easy way” |
日期 | Date | Sys.Date() |
時間 | POSIXct POSIXt | Sys.time() |
我們不需要自己去猜測,可以使用一個函數 class()
讓 R 語言告訴我們輸入的變數是什麼型別,就像在 RStudio 的左下角命令列(Console)輸入這些程式,詢問 R 語言它們的型別為何?
class(2)
## [1] "numeric"
class(2L)
## [1] "integer"
class(TRUE)
## [1] "logical"
class("Learning R the easy way")
## [1] "character"
class(Sys.Date())
## [1] "Date"
class(Sys.time())
## [1] "POSIXct" "POSIXt"
如果您對 class()
這個函數感到好奇,可以在命令列輸入 ?class
或者 help(class)
,這兩個指令都會在右下角打開文件。即便您對 class()
不甚感興趣,知道如何使用 ?
或 help()
進行查詢也相當有幫助。
8.2 數值
不論我們輸入的數字帶有小數位數或不帶有小數位數,R 語言預設儲存為數值(numeric)。
my_num <- 2.33
class(my_num)
## [1] "numeric"
my_num <- 2.0
class(my_num)
## [1] "numeric"
my_num <- 2
class(my_num)
## [1] "numeric"
8.3 整數
當我們輸入一個整數並加入 L
,R 語言就會儲存為整數(integer)。如果整數帶有不必要的小數位數,R 語言會回傳警示訊息但依舊會儲存為整數;但若在帶有小數位數的數字後加上 L
則 R 語言回傳警示訊息,並且忽略 L
儲存為數值。
my_int <- 2L
class(my_int)
## [1] "integer"
my_int <- 2.0L
class(my_int)
## [1] "integer"
my_int <- 2.33L
class(my_int)
## [1] "numeric"
8.4 邏輯值
當我們進行判斷條件或者篩選的時候就會需要使用邏輯值(logical),邏輯值只有 TRUE
與 FALSE
這兩個值,或者可以簡寫為 T
與 F
。
class(TRUE)
## [1] "logical"
class(FALSE)
## [1] "logical"
class(T)
## [1] "logical"
class(F)
## [1] "logical"
這裡要提醒您一個觀念,R 語言對大小寫是敏感的(case-sensitive),像是 TRUE
會被 R 語言識別為邏輯值,但是 True
與 true
則不會喔!
class(TRUE)
## [1] "logical"
class(True)
## Error in eval(expr, envir, enclos): object 'True' not found
class(true)
## Error in eval(expr, envir, enclos): object 'true' not found
除了直接輸入邏輯值,我們也可以透過判斷條件得到邏輯值的輸出:
8 > 7 # 判斷 8 是否大於 7
## [1] TRUE
8 < 7 # 判斷 8 是否小於 7
## [1] FALSE
8 >= 7 # 判斷 8 是否大於等於 7
## [1] TRUE
8 <= 7 # 判斷 8 是否小於等於 7
## [1] FALSE
8 == 7 # 判斷 8 是否等於 7
## [1] FALSE
8 != 7 # 判斷 8 是否不等於 7
## [1] TRUE
7 %in% c(8, 7) # 判斷 7 是否包含於一個 c(8, 7) 的向量之中
## [1] TRUE
我們稍微停頓一下,因為這裡有兩個新觀念需要您花點時間吸收:
c(8, 7)
是一種叫做向量的資料結構,我們會在之後的章節細談- 常用的判斷運算子有:
判斷運算子 | 作用 |
---|---|
== |
等於 |
> |
大於 |
< |
小於 |
>= |
大於等於 |
<= |
小於等於 |
!= |
不等於 |
%in% |
包含於 |
8.5 文字
在 R 語言中我們可以使用單引號(’)或雙引號(“)來建立文字(character),我的習慣是使用雙引號(”),所以在本書中的範例都會使用 "
來建立文字。
first_name <- 'Tony'
first_name
## [1] "Tony"
class(first_name)
## [1] "character"
8.5.1 日期
在 R 語言中被定義為日期(Date)的變數外觀看起來跟文字沒有什麼差別,但是我們一但將它們放入 class()
函數中檢驗,就會發現它並不是文字,我們接下來要使用的 Sys.Date()
是一個不需要任何輸入就會輸出電腦系統日期的函數。
sys_date <- Sys.Date() # 系統日期
sys_date # 看起來跟文字相同
## [1] "2018-05-12"
class(sys_date)
## [1] "Date"
而這兩個變數類型最大的分野,就在於日期是可以被轉換為整數,而文字是不行的:
sys_date <- Sys.Date()
sys_date_char <- as.character(sys_date) # 創造一個文字類型
as.integer(sys_date)
## [1] 17663
as.integer(sys_date_char)
## Warning: NAs introduced by coercion
## [1] NA
這裡我們使用的 as.character()
與 as.integer()
函數是 R 語言中用來進行變數類型轉換的函數,我們可以清楚文字類型的系統日期在轉換整數時失敗,以致於產生一個遺失值(Not Available,NA)。
那麼日期類型的系統日期轉換的整數是有什麼根據嗎?答案是有的,R 語言預設以西元 1970 年 1 月 1 日作為 0,在這一天以後的每天都 +1
來記錄,而這一天以前的每天都 -1
來記錄。
date_of_origin <- as.Date("1970-01-01")
as.integer(date_of_origin)
## [1] 0
as.integer(date_of_origin + 1)
## [1] 1
as.integer(date_of_origin - 1)
## [1] -1
date_of_origin
## [1] "1970-01-01"
date_of_origin + 1
## [1] "1970-01-02"
date_of_origin - 1
## [1] "1969-12-31"
也因為這樣的特性,日期類型可以進行四則運算,而文字類型不行:
sys_date <- Sys.Date()
sys_date_char <- as.character(sys_date) # 創造一個文字類型
sys_date - 1 # 昨天的日期
## [1] "2018-05-11"
sys_date_char - 1
## Error in sys_date_char - 1: non-numeric argument to binary operator
8.6 時間
在 R 語言中被定義為時間(POSIXct POSIXt)的變數外觀看起來跟文字同樣也沒有什麼差別,但是我們一但將它們放入 class()
函數中檢驗,就會發現它並不是文字,我們接下來要使用的 Sys.time()
是一個不需要任何輸入就會輸出電腦系統時間的函數。
sys_time <- Sys.time() # 系統時間
sys_time # 看起來跟文字相同
## [1] "2018-05-12 01:37:53 UTC"
class(sys_time)
## [1] "POSIXct" "POSIXt"
與日期相似,時間亦是可以被轉換為整數的:
sys_time <- Sys.time()
as.integer(sys_time)
## [1] 1526089073
與日期相似,R 語言預設以西元 1970 年 1 月 1 日格林威治標準時間(Greenwich Mean Time,GMT)00 時 00 分 00 秒作為 0,在這個時間點以後的每秒都 +1
來記錄,這個時間點以前的每秒都 -1
來記錄。
time_of_origin <- as.POSIXct("1970-01-01 00:00:00", tz = "GMT")
as.integer(time_of_origin)
## [1] 0
as.integer(time_of_origin + 1)
## [1] 1
as.integer(time_of_origin - 1)
## [1] -1
time_of_origin
## [1] "1970-01-01 GMT"
time_of_origin + 1
## [1] "1970-01-01 00:00:01 GMT"
time_of_origin - 1
## [1] "1969-12-31 23:59:59 GMT"
我們這裡所使用的參數 tz = "GMT"
是指定時區,假如您的電腦和我一樣時區是設在中原標準時間(Chungyuan Standard Time,CST),早格林威治標準時間八個小時(GMT + 8),則基準時間會是西元 1970 年 1 月 1 日 08 時 00 分 00 秒。
time_of_origin_cst <- as.POSIXct("1970-01-01 08:00:00")
as.integer(time_of_origin_cst)
## [1] 28800
8.7 數學運算
對數值,整數與邏輯值進行數學運算,常用的數學運算子有七種:
數學運算子 | 作用 |
---|---|
+ |
加 |
- |
減 |
* |
乘 |
/ |
除 |
^ 或 ** |
次方 |
%/% |
回傳商數 |
%% |
回傳餘數 |
我們先進行僅有數值的運算:
first_num <- 8
second_num <- 7
first_num + second_num
## [1] 15
first_num - second_num
## [1] 1
first_num * second_num
## [1] 56
first_num / second_num
## [1] 1.142857
first_num^second_num
## [1] 2097152
first_num**second_num
## [1] 2097152
first_num %% second_num
## [1] 1
first_num %/% second_num
## [1] 1
接著我們進行僅有整數的運算:
first_int <- 8L
second_int <- 7L
ans <- first_int * second_int
ans
## [1] 56
class(ans)
## [1] "integer"
ans <- first_int / second_int
ans
## [1] 1.142857
class(ans)
## [1] "numeric"
相乘之後仍然是整數的變數型別,注意相除之後 R 語言自動幫我們把答案轉換成了適當型別,我們時不時都可以觀察到 R 語言的彈性:
my_num <- 8
my_int <- 7L
ans <- my_num + my_int
class(ans)
## [1] "numeric"
最後我們把邏輯值也放進來做四則運算,看看會發生什麼事情:
my_num <- 8
my_int <- 7L
my_logi <- TRUE
ans <- my_num + my_int + my_logi
ans
## [1] 16
class(ans)
## [1] "numeric"
my_logi <- FALSE
ans <- my_num + my_int + my_logi
ans
## [1] 15
class(ans)
## [1] "numeric"
為什麼 TRUE
和 FALSE
納入四則運算沒有任何問題呢?原來在 R 語言中,TRUE
跟 1
或者 1L
是相等的;FALSE
跟 0
或者 0L
是相等的。
my_num <- 0
my_int <- 0L
my_logi <- FALSE
my_num == my_logi
## [1] TRUE
my_int == my_logi
## [1] TRUE
my_num <- 1
my_int <- 1L
my_logi <- TRUE
my_num == my_logi
## [1] TRUE
my_int == my_logi
## [1] TRUE
8.8 變數型別的判斷與轉換
R 語言針對變數型別的判斷除了使用 class()
函數直截了當告訴我們答案以外,也能夠使用一系列 is.型別名稱()
的函數回傳邏輯值,用 TRUE
或者 FALSE
回傳判斷的結果;而變數型別的轉換則是透過一系列 as.型別名稱()
的函數進行轉換。
8.8.1 變數型別的判斷
除了判斷日期與時間變數型別要使用的是 inherits()
函數,其他都可以使用 is.型別名稱()
這樣形式的函數判斷。
函數 | 範例 |
---|---|
is.numeric() |
is.numeric(7.7) |
is.integer() |
is.integer(7L) |
is.logical() |
is.logical(FALSE) |
is.character() |
is.character("Learn R the easy way") |
inherits(x, what = "Date") |
inherits(Sys.Date(), what = "Date") |
inherits(x, what = "POSIXct") |
inherits(Sys.time(), what = "POSIXct") |
8.8.1.1 判斷是否為數值
使用 is.numeric()
函數請 R 語言判斷這個變數是不是數值。
is.numeric(8.7)
## [1] TRUE
is.numeric("8.7")
## [1] FALSE
8.8.1.2 判斷是否為整數
使用 is.integer()
函數請 R 語言判斷這個變數是不是整數。
is.integer(7L)
## [1] TRUE
is.integer(7)
## [1] FALSE
8.8.1.3 判斷是否為邏輯值
使用 is.logical()
函數請 R 語言判斷這個變數是不是邏輯值。
is.logical(FALSE)
## [1] TRUE
is.logical("FALSE")
## [1] FALSE
8.8.1.4 判斷是否為文字
使用 is.character()
函數請 R 語言判斷這個變數是不是文字。
is.character("TRUE")
## [1] TRUE
is.character(TRUE)
## [1] FALSE
8.8.1.5 判斷是否為日期
使用 inherit(x, what = "Date")
函數請 R 語言判斷這個變數 x 是不是日期,Sys.Date()
是一個 Date
的型別,因此 inherit(Sys.Date(), what = "Date")
函數會回傳 TRUE
;而 "1970-01-01"
是一個 Character
的型別,inherit("1970-01-01", what = "Date")
函數會回傳 FALSE
。
inherits(Sys.Date(), what = "Date") # Sys.Date() 是日期型別
## [1] TRUE
inherits("1970-01-01", what = "Date") # "1970-01-01" 是文字型別
## [1] FALSE
8.8.1.6 判斷是否為時間
使用 inherit(x, what = "POSIXct")
函數請 R 語言判斷這個變數 x 是不是時間,Sys.time()
是一個 POSIXct
的型別,因此 inherit(Sys.time(), what = "POSIXct")
函數會回傳 TRUE
;而 "1970-01-01 00:00:00"
是一個 Character
的型別,inherit("1970-01-01 00:00:00", what = "POSIXct")
函數會回傳 FALSE
。
inherits(Sys.time(), what = "POSIXct") # Sys.time() 是時間型別
## [1] TRUE
inherits("1970-01-01 00:00:00", what = "POSIXct") # "1970-01-01 00:00:00" 是文字型別
## [1] FALSE
8.8.2 變數型別的轉換
使用 as.型別名稱()
這樣形式的函數進行轉換。
函數 | 範例 |
---|---|
as.numeric() |
as.numeric(7L) |
as.integer() |
as.integer(7) |
as.logical() |
as.logical("TRUE") |
as.character() |
as.character(Sys.Date()) |
as.Date() |
as.Date("1970-01-01") |
as.POSIXct() |
as.POSIXct("1970-01-01 00:00:00", tz = "GMT") |
8.8.2.1 轉換成數值
使用 as.numeric()
函數轉換變數為數值型別,我們可以輸入整數、邏輯值、日期或時間讓 R 語言轉換成數值。
as.numeric(7L)
## [1] 7
as.numeric(TRUE)
## [1] 1
as.numeric(FALSE)
## [1] 0
as.numeric(Sys.Date())
## [1] 17663
as.numeric(Sys.time())
## [1] 1526089073
8.8.2.2 轉換成整數
使用 as.integer()
函數轉換變數為數值型別,我們可以輸入沒有小數位數的數值、邏輯值、日期或時間讓 R 語言轉換成整數。
as.integer(7)
## [1] 7
as.integer(TRUE)
## [1] 1
as.integer(FALSE)
## [1] 0
as.integer(Sys.Date())
## [1] 17663
as.integer(Sys.time())
## [1] 1526089073
8.8.2.3 轉換成邏輯值
使用 as.logical()
函數轉換變數為邏輯值型別,輸入數值或整數型別的 0
會轉換成為 FALSE
,其他的數字則一律轉換為 TRUE
。
as.logical(0)
## [1] FALSE
as.logical(0L)
## [1] FALSE
as.logical(1L)
## [1] TRUE
as.logical(-1.3)
## [1] TRUE
as.logical(87)
## [1] TRUE
輸入文字型別的 "TRUE"
、"True"
或 "true"
則會轉換成為 TRUE
,反之亦同。
as.logical("TRUE")
## [1] TRUE
as.logical("True")
## [1] TRUE
as.logical("true")
## [1] TRUE
as.logical("FALSE")
## [1] FALSE
as.logical("False")
## [1] FALSE
as.logical("false")
## [1] FALSE
8.8.2.4 轉換成文字
使用 as.character()
函數轉換變數為文字型別,我們可以輸入任意的變數型別讓 R 語言轉換成文字。
as.character(8.7)
## [1] "8.7"
as.character(87L)
## [1] "87"
as.character(TRUE)
## [1] "TRUE"
as.character(Sys.Date())
## [1] "2018-05-12"
as.character(Sys.time())
## [1] "2018-05-12 01:37:53"
8.8.2.5 轉換成日期
使用 as.Date()
函數轉換變數為日期型別,我們可以輸入文字讓 R 語言轉換成日期。as.Date()
函數預設可以識別 %Y-%m-%d
或 %Y/%m/%d
這兩種格式。
as.Date("1970-01-01")
## [1] "1970-01-01"
as.Date("1970/01/01")
## [1] "1970-01-01"
如果是其他的格式,必須要加入 format
參數告知日期被記錄的文字格式為何,函數才能順利轉換,例如文字不是預設的格式,而是將月與日的資訊寫在年份的前面,沒有以 format
參數指定就會轉換成錯誤的日期:
as.Date("01-01-1970") # 轉換錯誤
## [1] "1-01-19"
as.Date("01-01-1970", format = "%m-%d-%Y") # 轉換正確
## [1] "1970-01-01"
as.Date("01/01/70") # 不是預設格式,轉換失敗
## Error in charToDate(x): character string is not in a standard unambiguous format
as.Date("01/01/70", format = "%m/%d/%y") # 轉換正確
## [1] "1970-01-01"
不同符號所代表的格式整理在下表:
符號 | 格式 | 範例 |
---|---|---|
%d | 日 | 01 |
%a | 禮拜幾的縮寫 | Mon |
%A | 禮拜幾 | Monday |
%m | 月 | 01 |
%b | 月名稱的縮寫 | Jan |
%B | 月名稱 | January |
%y | 兩位數的年 | 70 |
%Y | 四位數的年 | 1970 |
想查詢更多的格式,可以在 R Console 輸入 ?strptime
。
8.8.2.6 轉換成時間
使用 as.POSIXct()
函數轉換變數為時間型別,我們可以輸入文字讓 R 語言轉換成時間。如果沒有指定參數 tz =
會預設使用電腦的時區。
as.POSIXct("1970-01-01 00:00:00")
## [1] "1970-01-01 UTC"
as.POSIXct("1970-01-01 00:00:00", tz = "GMT")
## [1] "1970-01-01 GMT"