[R Lang] R Lang 與高級醫學統計學(3)

2024 年 4 月 9 日
文章摘要
FakeGPT
加載中...
此內容由人工不智慧生成。

這篇文章講 R Lang 中的資料物件。在 R Lang 中,資料物件可以是向量(vector)、矩陣(matrix)、陣列(array)、列表(lists)或資料框架(data frames)等。

矩陣 Matrix

矩陣是一個包含相同模式資料的二維度資料物件,大致相當於其他程式語言中的二維度數組的概念。

創建矩陣

使用函式 matrix() 來創建矩陣物件。該函式的定義如下:

matrix(data = NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL)

下面我們來解釋其中的引數:

  • nrow:正整數,設定列數(row numbers)
  • ncol:正整數,設定欄數(column numbers)
  • byrow:根據自動設定,欄位(column優先填滿)
  • dimnames:輸入列表設定列名與欄位名

使用 dim() 函式可以回傳具有維度數屬性的資料物件之維度大小。

下面我們來看一個例子:

## 因為 byrow 預設為 FALSE,因此遵循先欄後列的原則。
x <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 2)
x
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
dim(x) # 回傳值永遠是:欄數 列數,無關 byrow 的值
## [1] 2 3

矩陣命名

矩陣的命名包括欄位名和列名。命名可以使用函式 dimnames() 進行統一命名,也可以使用 rownames() 函式或 colnames() 單獨為列或欄命名。

x.mat <- matrix(1:6, nrow = 2, ncol = 3)
## 使用 dimnames() 函式統一命名,接受 list 引數
dimnames(x.mat) <- list(c("A1", "A2"),
c("B1", "B2", "B3"))
## 使用 rownames() 函式單獨為列命名
rownames(x.mat) <- c("A1", "A2")

矩陣下標索引 Matrix Index

很像 C++ 中的二維數組的下標。只不過在 C++ 中,用到的是 variable[i][j],而在 R Lang 中,使用 variable[i, j] 而已。當然,與向量相同,該下標系統具有更強大的特性,一樣可以使用正整數、負整數等等。而如果想要取到一整列,可以使用 variable[i, ] 即可。舉一反三,取到一整欄就是 variable[, j]

x <- matrix(c(1:12), nrow = 3, ncol = 4)
## 取到第 3 列第 2 欄的元素
x[3, 2]
## [1] 6
## 取到第 2 列
x[2, ]
## [1] 2 5 8 11
## 取到第 3 欄
x[, 3]
## [1] 7 8 9
## 取到 1,3 列和 2,4 欄的交會點
x[c(1, 3), c(2, 4)]
## [,1] [,2]
## [1,] 4 10
## [2,] 6 12
## 如果已經為欄或列命名,則可以使用名字的字串
dimnames(x) <- list(c("Row1", "Row2", "Row3"), c("Col1", "Col2", "Col3", "Col4"))
x["Row2", "Col2"]
## [1] 5

我們可以看到,我們取到的只有一欄或一列的時候,會發生維度塌方,生成向量。而如果希望保持 matrix 的形式,則可以加入第三個引數 drop = FALSE。例如:

x[1, , drop = FALSE]
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10

注意,和 C 家族語言中的無限 for 迴圈一樣,兩個逗號都不能省略,因為靠逗號來識別不同的引數。

向量與矩陣的合併

上一篇文章中我們提到,向量本身是沒有維度的。1×k1\times kk×1k \times 1 沒有區別。然而有的時候我們需要把向量和矩陣進行線性代數相關計算。

一個比較簡單的方法是,將其重新定義為 1×k1 \times kk×1k \times 1 的有維度 matrix。

x.vec <- c(1:6)
x.mat <- matrix(x.vec, nrow = 1)
x.mat
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 2 3 4 5 6

有時候我們需要把向量和矩陣或其他向量進行合併,成為一個新的矩陣,將該向量作為新矩陣的一欄或者一列。這時候,可以使用 cbind() 函式或 rbind() 函式。前者表示將向量作為新矩陣的一欄,後者則表示將向量作為新矩陣的一列。注意,如果向量的元素數量超過了矩陣的長度,則會報出一個 Warning,然後捨棄掉超過的內容。如果不足,則會報出一個 Warning,然後不足的內容開始重複填充,直到補足。

x.vec <- c(1, 2, 3)
y.vec <- c(8, 9, 10)
x.mat <- matrix(c(11:16), nrow = 2, ncol = 3)
x.vec2 <- c(1, 2)
rbind(x.vec, y.vec)
## [,1] [,2] [,3]
## x.vec 1 2 3
## y.vec 8 9 10
cbind(x.vec, y.vec)
## x.vec y.vec
## [1,] 1 8
## [2,] 2 9
## [3,] 3 10
rbind(x.mat, x.vec)
## [,1] [,2] [,3]
## 11 13 15
## 12 14 16
## x.vec 1 2 3
cbind(x.mat, y.vec)
## 在下面,我們看到了 Warning,超出長度的部分 10 被捨棄。
## Warning in cbind(x.mat, y.vec): number of rows of result is not a multiple of vector length (arg 2)
## y.vec
## [1,] 11 13 15 8
## [2,] 12 14 16 9
rbind(x.mat, x.vec2)
## 在下面,我們看到了 Warning,不足的部分開始重複第一個數字 1,直到補足為止
## Warning in cbind(z.mat, y.vec): number of rows of result is not a multiple of vector length (arg 2)
## [,1] [,2] [,3]
## 11 13 15
## 12 14 16
## x.vec2 1 2 1

陣列 Array

這個陣列和 Java 以及其他程式設計語言中的陣列完全不同。其他語言中的陣列等於數組,而在 R Lang 中,陣列是指包含相同模式 (mode) 的元素組成的 p 維資料物件

陣列的操作基本和矩陣相同。使用 array() 函式來創建陣列。函式定義如下:

array(data = NA, dim = length(data), dimnames = NULL)

按照慣例解釋引數:

  • dim:陣列的維度,以及每一個維度包含的元素個數。
  • dimnames:每一個維度的命名。

一樣可以使用 dimnames() 函式來為陣列的維度命名。rownames()colnames() 也同樣適用第一和第二維度。

關於下標系統,陣列和矩陣基本完全相同,只不過是有幾個維度上幾個引數而已。

由於篇幅原因,陣列部分就不放例子了。讀者可以自行回去試一下。

列表 List

R Lang 中列表的概念也同樣不同於其他我們所熟悉的程式語言。在 R Lang 中,列表事實上就是一個有序的物件的集合體。特別注意的是,在前面介紹的無論是向量還是矩陣,抑或是陣列,都特別表明“包含相同模式 (mode)”。而列表中的元素(稱作“成分”,component)的模式則是所謂的複雜模式,即沒有限制。

列表的產生

使用 list() 函式來產生列表。

通常情況下,我們先產生列表中的成分,再將成分組合成列表。

x.vec <- 1:4
y.vec <- c("Male", "Female")
z.mat <- matrix(1:9, nrow = 3, ncol = 3)
xyz.list <- list(x.vec, y.vec, z.mat)
xyz.list
## [[1]]
## [1] 1 2 3 4
##
## [[2]]
## [1] "Male" "Female"
##
## [[3]]
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9

也可以在定義列表的時候,為每一個成分命名:

x.num <- c(1, 3, 6)
y.str <- c("chocolate", "vanilla", "strawberry")
xy.list <- list(x.num.var = x.num, y.str.var = y.str)
xy.list
## $x.num.var
## [1] 1 3 6
##
## $y.str.var
## [1] "chocolate" "vanilla" "strawberry"

列表的下標與索引 List Index

列表的下標系統和向量、矩陣、陣列有所不同。當我們使用 [] 的時候,取到的仍然是list模式的component,而不是我們塞進去的物件。要取到我們的物件,需要使用 [[]]

x.vec <- 1:4
y.vec <- c("Male", "Female")
z.mat <- matrix(1:9, nrow = 3, ncol = 3)
xyz.list <- list(x.vec, y.vec, z.mat)
xyz.list[1]
## [[1]]
## [1] 1 2 3 4
xyz.list[[1]]
## [1] 1 2 3 4

若已經為成分命名,則可以使用成分名字來直接訪問到成分或其代表的物件。這裡有兩種方式,可以使用 list.Name[["com.Name"]] 的傳統方式,也可以使用 list.Name$com.Name 的方式。這兩種方式沒有任何區別。

x.num <- c(1, 3, 6)
y.str <- c("chocolate", "vanilla", "strawberry")
xy.list <- list(x.num.var = x.num, y.str.var = y.str)
xy.list[["x.num.var"]]
## [1] 1 3 6
xy.list$y.str.var
## [1] "chocolate" "vanilla"

資料框架 Data Frame

事實上,前面我們所講到的矩陣,我們可以把它看作是二維度表格,陣列則是多維度表格。然而,這些表格有一個限制,那就是元素的模式必須是相同的。

資料框架事實上也是一個二維表格,但與矩陣不同的是,它的元素模式可以是不同的。

創建資料框架

使用 data.frame() 函式來創建資料框架。

id.vec <- c(1, 2, 3, 4)
age.vec <- c(35, 55, 45, 25)
sex.vec <- c("Male", "Male", "Female", "Female")
disease.vec <- c("Yes", "No", "No", "Yes")
x.df <- data.frame(
id = id.vec,
age = age.vec,
sex = sex.vec,
disease = disease.vec
)
x.df
## id age sex disease
## 1 1 35 Male Yes
## 2 2 55 Male No
## 3 3 45 Female No
## 4 4 25 Female Yes

資料框架的下標與索引 Data Frame Index

有兩套體系。一套是類似於矩陣的樣子,使用 [i, j] 來獲取元素,另一套則是類似於列表,使用 [[]] 來獲取成分中的物件。

id.vec <- c(1, 2, 3, 4)
age.vec <- c(35, 55, 45, 25)
sex.vec <- c("Male", "Male", "Female", "Female")
disease.vec <- c("Yes", "No", "No", "Yes")
x.df <- data.frame(
id = id.vec,
age = age.vec,
sex = sex.vec,
disease = disease.vec
)
x.df[1, 2]
## [1] 35
x.df[2]
## age
## 1 35
## 2 55
## 3 45
## 4 25
x.df[[2]]
## [1] 35 55 45 25
[R Lang] R Lang 與高級醫學統計學(3)
https://blog.kynix.tw/posts/1731062135356/
作者
Adrian Chen
建檔時間
2024 年 4 月 9 日
協議
BY-NC-SA 4.0
姓名標示-非商業性-相同方式分享 4.0 國際