[R語言初學] R語言當中的資料型態

2

Last Updated on 2023-10-22

Home » R語言教學 » R語言初學 » [R語言初學] R語言當中的資料型態

什麼是資料型態?和資料結構有何差異?R語言當中有什麼常見的資料型態?本文告訴你


你可能聽過資料結構(data type)與資料型態(data type),但是不知道兩者有什麼差別。請別灰心,這很自然,我剛學的時候也會混淆。

本文會介紹R語言當中的資料型態,包含字元、數值、日期、布林邏輯等,並一併告訴大家如何判斷資料型態,還有轉換資料型態的具體方法。

資料結構指的是程式語言中,資料儲存的長相或者形式,例如我們平常時常見到的表格,就是一種以行與列儲存資料的長相;假設有張紙條上面記載著一連串的數字,這樣也是一種資料結構。

至於資料型態,則是指資料的類型,例如資料的原始型態為數值,也可能是字串,又或者是布林邏輯的值(TRUEFALSE)。

簡單來說,資料型態是資料的最基本單元,資料結構則是將資料組合在一起的方法。

如果以搭建房子比喻儲存資料,資料結構就是房屋的架構,有可能是用行列搭建,也可能採不規則的樑柱排序;資料型態則像是建材的材質,房子可能是木頭質地的,也可能用磚砌。無論是何者,主要看使用者的資料有何特點,像是國中某班某次段考30位同學的成績,就適合用資料表這種資料結構儲存,分數的資料型態則很明顯是數值。

我們會在這篇文章中介紹R語言當中的資料型態。

觀念釐清:資料型態、資料結構與資料格式的差異

我們來複習一下資料型態(Data Type)、資料結構(Data Structure)與資料格式(Data Format)的意義跟差別。

資料型態(Data Type)

  • 意義:資料型態指資料儲存的原始型態,可以說是資料的最小單位。
  • 範例:integer, float, string, boolean 等。

資料結構(Data Structure)

  • 意義:資料結構指將資料組合後儲存的長相與形式。
  • 範例Array, Linked List, Stack, Queue, Tree, Graph 等。在R語言當中以vector, list, dataframe為主。

資料格式(Data Format)

  • 描述:資料格式指資料儲存的規範或標準,用來定義交換、展示與儲存資料在文件或其他媒介中的方法。
  • 範例CSV, JSON, XML, JPEG, MP3 等。在R語言當中最有特色的是RDS,只能用R語言打開。

關係與差異

  1. 資料型態是最基本的單位,用於界定變數或對象可以存儲哪種類型的數據。
  2. 資料結構是由多個資料型態的資料組成,用來提升儲存、排序、搜尋資料的效率。
  3. 資料格式更往上一層,規定了(用特定資料結構儲存的)資料(用特定資料結構已經組織在某種 Data Structure 中)如何存在電腦裡、與他人交換。

總結來說,資料型態最基礎,資料結構由資料型態組合而成,而資料格式則是用於儲和存交換資料結構和資料型態的標準或規範。

以台灣籃球聯盟T1為例,想看某場比賽球員的表現,球員名字以character的資料型態儲存、得分以integer的資料型態儲存,將兩者以資料結構組合成dataframe,再輸出成csv, xlsx,讓其他人也能方便讀取。

R語言中的資料型態

R語言中有許多的資料型態,其中,最常用的是底下這4種:數值、字元、布林邏輯、日期。

數值

可以用平常見到的「數字」理解數值型態,例如3.149.8等等都屬於數值類型。不過,有些看起來屬於數值類型的資料,其實是以其他資料型態存在,像是整數型態(Integer)和複數型態(Complex)的數值,前者像是
123,後者則像1+2i3+4i

實務上最常混淆數值與整數,同樣都是1這個數字,若是數值型態,會是1.0,整數型態則是1,兩者看起來沒有差別,但是在後面碰上資料結構時,就會顯現出差異。

例如向量(vector)的儲存規則為每個元素(element)的資料型態必須相同,若有人三次段考的分數分別為
9090.191.9,以數值型態儲存則沒有問題,但如果是以整數型態儲存,則會四捨五入。

# numeric
c(90,90.1,91.9)
#> [1] 90.0 90.1 91.9
# integer
as.integer(c(90,90.1,91.9))
#> [1] 90 90 91

在上方的程式碼中,as.integer()是一個函數(function),它可以把其他資料型態的變數轉換為整數。

函數是什麼呢?簡單來說,就是使用者輸入值後,按照特定邏輯輸出結果的方法,例如在學校學過的 y = ax + b,若 a = 2, b = 1,我們只要輸入 x = 1,就會得到y = 3,這就是一個函數。

字元

可以用書本上或是文章中的「文字」理解字元型態,無論是"你好嗎""Halo",或者"3.14"都屬於字元型態。不過,為什麼"3.14"不是數值而是字元呢?因為我們在外面已經先用引號將其包覆,在R語言當中,無論是單引號或者雙引號,只要包覆了文字或者數字,都會變成字元型態,也因此無法再拿"3.14"進行四則運算了。

3.14 + 1.86
#> [1] 5
"3.14" + 1.86
#> Error in "3.14" + 1.86: 二元運算子中有非數值引數

上面這串## Error in "3.14" + 1.86: non-numeric argument to binary operator文字,就是執行程式碼出錯時會跳出的訊息。我自己剛學R的時候看到錯誤訊息,臉都會很臭,因為代表我的程式碼寫錯了,接下來會開始怨天尤人,不想看懂只想改對,有時候則會搖尾乞憐,請前輩幫忙指點。後來才知道,學會閱讀錯誤訊息是學程式的重要課題,因為只有看懂才能知道該如何。

細看上面的訊息,前半段"Error in "3.14" + 1.86 :"是出錯的程式碼內容,後半段non-numeric argument to binary operator又可以分為兩半,後面的”binary
operator”當中的binary就是雙元,因此”binary
operator”翻譯成二運算子,顧名思義就是指運作於兩個運算元的運算子。

什麼是運算元跟運算子?就算不懂也沒關係,單純看"3.14" + 1.86這個算式,裡面的加號處理的兩個運算元為"3.14"1.86,加號本身就是"binary operator"

看懂後面,前面就好懂了,non-numeric argument直翻為非數值的參數,因為"3.14"屬於字元型態,不是數值型態,但是加法這個二元運算子只能處理數值,我們丟了一個字元給它,它就出錯了,所以整體來看,non-numeric argument to binary operator就是在說我們把一個非數值的參數(也就是"3.14")丟給一個二元運算子(也就是加號),所以報錯。

底下我們分別看把字元變成數值,以及數值變成字元的結果。

# 字元變數值
as.numeric("3.14")
#> [1] 3.14
# 數值變字元
as.character(3.14)
#> [1] "3.14"

布林邏輯

布林邏輯聽起來很神祕,但其實就是以前考試是非題當中的「是」與「非」。「是」對應到TRUE,「非」對應到FALSE,也可以用單一個大寫字母TF代替。

我們可以用比較運算子(comparison operators)或者邏輯運算子(logical
operators)產出布林邏輯型態的資料:

2 > 1
#> [1] TRUE
(2 > 1) & (2 > 3)
#> [1] FALSE

第一行程式碼是運用比較運算子單純的比大小,第二行則是運用邏輯運算子中「且」的概念,因為沒有同時滿足,所以結果為
FALSE

其他的比較運算子包含:

  • >:大於
  • <:小於
  • >=:大於等於
  • <=:小於等於
  • ==:等於
  • !=:不等於

其他的邏輯運算子包含:

  • & 以及 &&:且:大於
  • | 以及 ||:或
  • !:否

要怎麼用這些運算子呢?後續會再介紹。另外需要注意的是,R語言的程式碼對於大小寫是敏感的(case sensitive),TRUE不能寫成True,所以底下程式碼的第二行會報錯。

TRUE
#> [1] TRUE
True
#> Error in eval(expr, envir, enclos): 找不到物件 'True'

日期

日期可以說是資料型態中,相對複雜難解的一種。它的加減運算不同於數值,想要提取年月日需要特定的函數,而且呈現方式也不只有數字,可能會用上英文的月份名稱,有時是全名有時是簡寫。

Sys.Date()
#> [1] "2023-02-28"
months(Sys.Date())
#> [1] "二月"

若單獨出現日期也就算了,再加上時間(time)會更需要花心思處理,有專門的套件(library)例如lubridate可以對付日期與時間,之後在應對日期時間資料的章節會細談。

資料型態判斷與轉換

這個小節中,我們主要會介紹資料型態的判斷與轉換。

資料型態判斷

如同上面的介紹,R語言當中有好幾種資料型態,如果第一眼看到資料,不確定是什麼型態時,可以先用class()函數查看資料型態。

class(1)
#> [1] "numeric"
class(1.0)
#> [1] "numeric"

欸,為什麼兩個都是數值變數,第一行不應該是整數嗎?因為如果想創建整數,需要明確地在數字後面加上”L”,若沒有加上,就會自動當成數值。

1L
#> [1] 1
class(1L)
#> [1] "integer"
1
#> [1] 1
class(1)
#> [1] "numeric"

想要判斷資料型態,除了使用 class() 以外,還能使用is._()開頭的函數,確認某個變數是不是那個資料型態。

is.integer(1L)
#> [1] TRUE
is.character("你好嗎")
#> [1] TRUE

資料型態轉換

若是想要轉換資料型態,可以利用as._()開頭的函數。這邊會介紹一些轉換時的獨特情形,還請細細參詳。

# character to integer
as.integer("10")
#> [1] 10
# character to integer
as.integer("十")
#> Warning: 強制變更過程中產生了 NA
#> [1] NA

在上面的案例中,"10"本來是字元,但因為雙引號中的文字可以變成整數,因此可以成功轉換,但國字"十"沒有辦法變成數字,所以就會變成代表遺失值(missing value)的NA了。這個NA看起來毫不起眼,日後卻會反覆出現。

# character to integer
as.integer("10.4")
#> [1] 10
# character to numeric
as.numeric("10.4")
#> [1] 10.4

雖然都是10.4,但as.integer()會四捨五入,as.numeric()則不會。接下來則是常用的布林邏輯轉數字,TRUE轉換為數值或者整數,都會變成1FALSE則會變成0。這有什麼要緊呢?在日後使用條件判斷式 if-else statement 的時候,我們有時候會拿條件判斷的結果來運算,這時就會將TF從布林邏輯值轉換成數字了。

# boolean to integer
as.integer(T)
#> [1] 1
# boolean to integer
as.integer(F)
#> [1] 0
# +,-,*,/
is.numeric("10")+is.numeric(10)
#> [1] 1

我們同樣可以將數值或整數轉換成布林邏輯值,但需要注意的是,只有0可以變成FALSE0以外的數值都會轉變成TRUE

# numeric to boolean
as.logical(1)
#> [1] TRUE
as.logical(2)
#> [1] TRUE
as.logical(-1)
#> [1] TRUE
as.logical(-2)
#> [1] TRUE
# numeric to boolean
as.logical(0)
#> [1] FALSE

至於日期,可以從字串得來,還可以轉換成數字。為什麼可以轉換成數字呢?因為R語言中,將1970-01-01設定為日期的開始,當天對應的數值為0,每往後一天就會加上1,每往前一天則會減去1。

# date to numeric
as.numeric(as.Date("2023-02-01"))
#> [1] 19389
as.numeric(as.Date("1970-01-01"))
#> [1] 0
# character to date
as.Date("2023-02-01")
#> [1] "2023-02-01"
as.Date("2023/02/01")
#> [1] "2023-02-01"

另外,as.Date()可以指定字元的格式,藉此判斷使用者提供的字串中,哪些可以對應到年月日。

# character to date
as.Date("2023-02-01", format = "%Y-%m-%d")
#> [1] "2023-02-01"
as.Date("20230201", format = "%Y%m%d")
#> [1] "2023-02-01"
as.Date("02/01/2023", format = "%m/%d/%Y")
#> [1] "2023-02-01"
as.Date("二月 01 2023", format = "%B %d %Y")
#> [1] "2023-02-01"

底下整理一個表格供參考,可以讓R語言知道你的原始日期格式到底是什麼。

符號對應例子
%Y年,四字 2023
%y年,兩字 23
%m月,兩字 01
%B月,完整單字 March/三月
%b月,簡寫單字 Mar/三月
%d日,兩字 31
%A星期幾,完整 Monday/週一
%a星期幾,簡寫 Mon/週一

到這裡差不多介紹完了R語言當中的資料型態,以及不同資料型態的判斷與轉換方法,下邊則要討論怎麼在R語言裡面基本運算啦!

小結

我們在這篇文章中認識了R語言當中的資料型態,接下來則會找機會介紹R語言裡的基本運算。希望你喜歡這篇文章。

2 Comments

  1. I may need your help. I tried many ways but couldn’t solve it, but after reading your article, I think you have a way to help me. I’m looking forward for your reply. Thanks.

  2. Reading your article helped me a lot and I agree with you.

Leave a Reply