R 語言資料型態補充

基本的資料型態在實際運用上,還是有些眉眉角角的,讓我們來看看各類型的資料型態功用及語法吧!

  1. 向量 Vectors

在 R 裡,一個範圍(如 1 – 10)的表示不像 Ruby 中使用 for a in 1..10,而是 a <- 1:10,把 1 – 10 這個範圍的數字 assign 給 A (等於 = 這個符號在 R 裡也是 assign,等於等於 == 是判斷左右兩邊是否相等)

> A <- 4:10
> A

[1]  4  5  6  7  8  9 10

想知道向量中第 N 個元素是什麼,此時用中括號 [] 作為索引,像我想知道 A 向量中第 2、5 個元素為何:

> A[c(2,5)]

[1] 5 8

也能用中括號 [] 去更新指定位置元素的數值,像我想指定 A 中第二個元素變成 5 倍

> A[2] <- 5 * A[2]

> A
[1]  4 25  6  7  8  9 10

中括號還能篩選特定的數值,假設學生名單有三個人 (Intern 實習醫師看得太走火入魔),StudentList == "George" 是指 R 會去比對名單中每位同學跟 George 是否相符,結果是「真 假 假」

> StudentList <- c("George", "Meredis", "Derick")

> StudentList == "George"
[1]  TRUE FALSE FALSE

此時,用中括號去篩選哪個名單裡的人是 George

> StudentList[StudentList == "George"]
[1] "George"

2. 矩陣 Matrices
R 裡頭矩陣的元素優先填入 column (直的那排),填完第一個 column 再去填第二、三… 個。

> C <- matrix( c('1','3','5','5','3','1'), nrow = 2, ncol = 3)
> print(C)

     [,1] [,2] [,3]
[1,] "1"  "5"  "3" 
[2,] "3"  "5"  "1" 

此時,如果希望改成先填 row (橫),可以加個 byrow = TRUE 就行~

> C <- matrix( c('1','3','5','5','3','1'), nrow = 2, ncol = 3, byrow = TRUE)

> print(C)

     [,1] [,2] [,3]
[1,] "1"  "3"  "5" 
[2,] "5"  "3"  "1"

前面有提過,如果要放的資料不只一個維度,可用陣列 array(不過好像不常用),裡面放的資料要是同一種屬性。如今我們來存 2 個 4×4 的矩陣 (4×4 的矩陣是二維,存 2 個這樣的矩陣,資料就變成三維) 吧!

> Fruit <- array(c('banana', 'lemon', 'mango', 'cherry', 'watermelon'), dim = c(4, 4, 2))

> print(Fruit)
, , 1

     [,1]     [,2]         [,3]         [,4]        
[1,] "banana" "watermelon" "cherry"     "mango"     

[2,] "lemon"  "banana"     "watermelon" "cherry"    
[3,] "mango"  "lemon"      "banana"     "watermelon"
[4,] "cherry" "mango"      "lemon"      "banana"    


, , 2

     [,1]         [,2]     [,3]         [,4]        

[1,] "lemon"      "banana" "watermelon" "cherry"    
[2,] "mango"      "lemon"  "banana"     "watermelon"
[3,] "cherry"     "mango"  "lemon"      "banana"    
[4,] "watermelon" "cherry" "mango"      "lemon"

接下來是簡單的矩陣預算,先給出兩個矩陣 A、B:

> A <- matrix(c(1,3,5,7), nrow = 2, ncol = 2)
> B <- matrix(c(2,1,3,1), nrow = 2, ncol = 2)

> A
     [,1] [,2]
[1,]    1    5
[2,]    3    7
> B

     [,1] [,2]
[1,]    2    3

[2,]    1    1

(1) A * B:矩陣 A 與 矩陣 B 的元素間倆倆相乘,也就是很純粹的 Aij x Bij 後把它填到新的矩陣第 ij 個值,跟高中學的矩陣加法不一樣喔

> A * B
     [,1] [,2]
[1,]    2   15

[2,]    3    7

(2) A %*% B:矩陣乘法 A⋅B,這才是我們以前學的矩陣乘法,新的矩陣第 ij 個值,是由 A 第 i 個 row 乘上 B 第 j 個 column 各自的值,並且加在一起

> A %*% B
     [,1] [,2]

[1,]    7    8

[2,]   13   16

(3) t(A):轉置矩陣 AT

> t(A)
     [,1] [,2]
[1,]    1    3
[2,]    5    7

(4) solve(A):矩陣 A 的反矩陣

> solve(A)

       [,1]   [,2]
[1,] -0.875  0.625
[2,]  0.375 -0.125

(5) solve(A, b):求聯立方程組 Ax=b 的解,就是 A 的反矩陣乘上 b(還是要花點腦袋想一下,隔太久了~)
假設 b 向量是 (2,10)

> b <- c(2,10)
> solve(A, b)

[1]  4.5 -0.5

就得到 b 了!如果拿 A 的反矩陣,直接乘上 b 也會得到一樣的結果

> solve(A) %*% b
     [,1]
[1,]  4.5
[2,] -0.5

3. 列表 Lists
向量要放的是同類型的元素,比如數字、字串。不過列表可以存放任何我們想放的資料形式,要放向量、數字、函數都可以,還蠻常用的

> # Create a list.
> list1 <- list(c(1,2,3), 99.3, sin)

> 

> # Print the list. 比如說這列表第一個位置就是個向量~
> print(list1)
[[1]]
[1] 1 2 3

[[2]]

[1] 99.3

[[3]]
function (x)  .Primitive("sin")

也可以指定 List 裡每個位置要叫什麼名字,如第一個位置叫做 vector、第二個位置叫做 numeric… 再用 names() 指令叫出每個位置的名字

> # Create list and assign variable names.
> list2  <- list(vector = c(1,2,3),

+                numeric = 99.3,
+                func = sin)
> 

> # Print names of list and list itself.

> names(list2)
[1] "vector"  "numeric" "func"   
> 

> print(list2)
$vector
[1] 1 2 3

$numeric
[1] 99.3


$func
function (x)  .Primitive("sin")

4. 因子 Factors
專門儲存類別資料的變數,比如說有 100 個男生、女生,「性別」就會變成一個因子,裡面包含兩種類型,男生 (male, 字串) 當成 1 (數字)、女生 (female, 字串) 當成 2 (數字) 來做標記。所以,因子可用向量來呈現,具有字串及整數的特性,會儲存 (1) 特定的 Labels 比如男、女生;(2) 每個對應到 Labels 的元素,可用向量表示,如男男女 -> 112。
好處是如果有很多不同的類別、Label 在儲存的時候會存成文字的方式,占比較多的空間;如果我們存成因子的話,會變成一個 unique list,它只要存成字串與整數的方式,較省記憶體。老師建議,因為 R 裡面很多的模型(如回歸等),遇到因子物件的時候會自動做處理,所以如果遇到類別變數,可以盡量把它存成因子的方式,建模很好用。

> # Create a vector. 蘋果的顏色有:green green yellow red red red green,原先是存成一個向量,內容存的都是一個個字串

> apple_colors <- c('green','green','yellow','red','red','red','green')

> 
> # Create a factor object. 我們可以把它變成因子、轉化成 factor,用 factor (想轉換的東西) 把後面我們要的這個物件轉換成 factor

> factor_apple <- factor(apple_colors)

> 
> # Print the factor. 把它印出來看看,會發現裡面有一個 levels:green red yellow,R 會把它存成 1 1 2 3 3 3 1 的形式,再把它跟 green red yellow 去 mapping,這樣存會比較節省空間,並可以用nlevels來知道因子裡面有多少個不同的level
> print(factor_apple)

[1] green  green  yellow red    red    red    green 
Levels: green red yellow
> 

> print(nlevels(factor_apple))

[1] 3

5. 資料框架 Data Frames
這是 R 語言裡面為人津津樂道的一種資料結構,不過版本比較舊,現在新版叫做 tibble,之後二煎拌學了再跟大家分享~
上次有提過 Data Frames 有兩個原則,Rows 通常代表純個體 Individuals、或觀察對象 Observations,Columns 通常都是純變數 Variables

舉例:假設我們有三個變數,分別是名字、年齡、性別

> name <- c("George", "Dereck", "Ezi")
> age <- c("24", "35", "26")
> gender <- c("Male", "Male", "Female")

> 

> # Create by variables 用 data.frame 把三個變數 name age gender 括號起來,再指派給 data1,並印出來看看 data1 裡面到底長什麼樣子?

> data1 <- data.frame(name, age, gender)
> data1

    name age gender
1 George  24   Male
2 Dereck  35   Male
3    Ezi  26 Female

我們發現 print 出來的結果中,column 都是變數:第一個 column 是姓名、第二個 column 是年齡、第三個 column 是性別,而每一個 row 都是一個個體的資料。因此 dataframe 跟一般的資料集合是很相近的,這就是為什麼 R 的 dataframe 這麼好用;在 Python 的 Pandas 也是以 dataframe 為基礎的資料結構去做分析的~

當然我們也可以指派 dataframe 的名字,把 name age gender 等於後面的向量,就不用像前面打成三個地方,在裡面直接指派就好。
*記得這邊的等號不可以寫成指派符號,因為前面已經有一個指派符號了,所以後面只能寫等號!老師建議不要把等號跟指派符號混在一起寫。把 data2 印出來,會發現跟 data1 是一模一樣的!

> data2 <- data.frame(
+   name = c("George", "Dereck", "Ezi"),

+   age = c("24", "35", "26"),
+   gender = c("Male", "Male", "Female")
+ )
> data2
    name age gender

1 George  24   Male
2 Dereck  35   Male
3    Ezi  26 Female

在 data frame 裡,還有一些常用的函數:

  • head:取得資料框架前六比資料(預設是 6)。
  • colnames:修改或查詢 column 名稱。
  • rownames:設定 row 的名稱
  • summary:顯示資料基本資訊。

想要知道 data2 的前六筆資料是什麼,我們就可以用 head(data2)。因為 data2 只有三筆資料,所以會直接看到所有的資料結果;但是如果一個 dataframe 有一萬個個體,用 head() 只會輸出前六個資料

> head(data2)
    name age gender
1 George  24   Male

2 Dereck  35   Male
3    Ezi  26 Female

我們也可以把 data2 的 column name 指派成別的名稱,比如原本是 name age gender、想把它改成 Var_1 Var_2 Var_3,並把 data2 的 row names 做調整,再印出來看看,可以發現我們的 column name 真的被改成 Var_1, Var_2, Var_3 了~

> colnames(data2) <- c("Var_1", "Var_2","Var_3")
> rownames(data2) <- c("a", "b", "c")

> data2
   Var_1 Var_2  Var_3
a George    24   Male
b Dereck    35   Male

c    Ezi    26 Female

此外,還能看資料的統計,用 summary(data2) 來看看統計的結果。

> summary(data2)
    Var_1              Var_2              Var_3          
 
Length:3           Length:3           Length:3          
 
Class :character   Class :character   Class :character  
 
Mode  :character   Mode  :character   Mode  :character

資料結構在 R 裡面很常用,不過因為它有些小缺點,老師還是建議大家用 tibbles,而不要用這種 dataframe 架構去存資料,程式的效能會好非常多。


6. 資料結構的常用函數
操作資料時的常用函數

  • length(object) : 元素個素
  • unique(object) : 該物件的獨立元素
  • str(object) : 輸出該物件的基本架構
  • class(object) : 該物件屬於哪種資料結構
  • names(object) : 物件中元素的名稱
  • c(object,object,…) : 將物件合併為一個向量
  • object : 印出物件
  • rm(object) : 從工作空間中移除物件

length(object) 抓出一個向量或資料結構的長度,比如把向量 c(1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8) 指派給 x,總共有 12 個元素

> x <- c(1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8)

> length(x)

[1] 12

unique(object) 把 x 裡面所有獨立不重複的值找出來

> unique(x)
[1] 1 2 3 4 5 6 7 8

先來建立一個 data3 來進行後續的操作

> data3 <- data.frame(
+   name = c("Ezi", "Meredith", "Dereck", "Ezi", "Meredith"),
+   age = c("24", "25", "36", "24", "30"),
+   gender = c("Female", "Female", "Male", "Female", "Female")
+ )
> data3

      name age gender
1      Ezi  24 Female
2 Meredith  25 Female
3   Dereck  36   Male
4      Ezi  24 Female
5 Meredith  30 Female

我們會發現,Ezi 是重複的,因為第一、四個 Row 的內容完全一樣;而第二、五個 Row 的 Meredith 看似相同,但在年齡上有點不一樣,第五個 Row 是 Meredith 30 歲的時候(Grey Anatomy 不知第幾季了)~這時,如果用 unique() 操作會如何呢?

> unique(data3)
      name age gender

1      Ezi  24 Female

2 Meredith  25 Female

3   Dereck  36   Male

5 Meredith  30 Female

第四個 Row Ezi 被去掉了,只剩下1 2 3 5 這四個人的 row 還留著~

> str(data3)
'data.frame':	5 obs. of  3 variables:
 
 $ name  : chr  "Ezi" "Meredith" "Dereck" "Ezi" ...
 $ age   : chr  "24" "25" "36" "24" ...

 $ gender: chr  "Female" "Female" "Male" "Female" ...

string(data3) 可以把 data3 的相關變數做統計,讓我們知道裡面存了什麼東西:三個 factor 分別是 name age gender

> class(data3)

[1] "data.frame"

想知道 data 3 是怎麼樣的資料結構,就可以用 class() 來看看它屬於哪一類,結果發現它在 R 裡面存的是data.frame的形式~

> names(data3)

[1] "name"   "age"    "gender"

想叫出變數的名字可用 names (),得到變數、也就是 Column 的名字


今天上了九小時的班,下班後吹著台北車站週遭的微風(果然微風是要開在北車的?),回家吃晚餐都已經晚上九點多了,但每天堅持學習非原本領域的知識,還是一件非常令我充滿能量的事。相信你也可以!

我自學程式有許多管道,身為一個超級廢新手,主要來源包含買書、大神們的部落格、線上課程(Hahow / Udemy / Coursera)… 等。

附上手邊的幾個部落格和線上課程網址:

Leave a Reply

Your email address will not be published. Required fields are marked *