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

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

這篇文章講 R Lang 的基本物件類型——向量(vector)。

向量的基本概念

向量(vector)是指具有相同模式(mode)的元素組成的集合。其實就是其他程式語言中“數組”的概念。作為一門專攻統計學的程式設計語言,R Lang 的基本運算單位並不是其他語言的單一變數,而是變數的群體。這個群體的最小體現就是向量。在 R Lang 中,單一數值的變數可以被看作長度為 1 的向量。

向量並不具有維度。例如 c(1, 2, 3) 可以看作 1×31\times 3 的矩陣,也可以看作 3×13\times 1 的矩陣。

向量的基本資料類型(模式)

可以透過 class() 函式來查看一個變數的模式,透過 is.mode() 函式來判斷變數是否是某種模式。

class(x) # 查看變數 x 的模式
## [1] "numeric"
is.numeric(x) # 判斷變數 x 是否是 numeric 類型
## [1] TRUE

基本模式有下面幾種:

numeric

數值型,也即其他語言的“浮點型”,包含單精度浮點型(single)和雙精度浮點型(double)。

pi <- 3.14

integer

整數型,需要在值後面加上 “L”,否則解釋器講自動將其歸為numeric類型。整數性可以算作數值型的一個特例,因此使用 is.numeric() 函式仍然返回為 TRUE。

x <- 2L
is.integer(x)
## [1] TRUE
is.numeric(x)
## [1] TRUE

logical

布林型,取值為 “TRUE(T)” 或 “FALSE(F)”,或者用 1 和 0 分別代表 T 和 F。

x <- TRUE
class(x)
## [1] "logical"

complex

複數型

x <- 3 + 5i
class(x)
## [1] "complex"

character

文字或字串。在 R Lang 中並未區分字元和字串這兩個概念。事實上一個字元就可以看作只包含一個字元的字串。在 R Lang 中統一使用雙引號。

x <- "Hello, world."
class(x)
## [1] "character"

向量的產生和運算

使用 c() 函式即可產生一個向量。

x <- c(1, 2, 3)
class(x)
## [1] "numeric"

向量的元素命名

向量中的每一個元素都可以進行命名。可以在定義的時候直接命名或者在後期使用 names() 函式來進行命名。

x <- c(
age = 50,
chol = 220,
dbp = 84,
sbp = 132
) # 直接命名
y <- c(50, 220, 84, 132)
names(y) <- c("age", "chol", "dbp", "sbp") # names() 函式命名

向量的下標與索引

類似於其他程式語言中數組可以透過下標 Index 訪問,向量也一樣可以。但是在 R Lang 中向量的下標系統相比其他語言更加強大。R Lang 的下標支援正整數、負整數、文字、字串、邏輯向量。

正整數

第幾個元素。於其他程式語言相同。但是特別注意,R Lang 中下標從 1 開始算起,而不是我們熟悉的從 0 開始。

x <- c(0:5) # 用:來宣告從 0~5
x[2]
## [1] 1

負整數

返回原向量中排除負整數後的向量結果

x <- c(0:5)
x[-c(2, 4)] # 從向量 x 中排除第 2 個和第 4 個元素
## [1] 0 2 4 5

文字

如果給向量元素命名過,我們就可以使用字串作為 Index 來查找對應的元素。

x <- c(0:5)
names(x) <- c("num0", "num1", "num2", "num3", "num4", "num5")
x[c("num2", "num4")]
## num2 num4
## 2 4

邏輯向量

直接將邏輯向量作為 Index,以從目標向量中篩選出符合邏輯的子向量。

x <- c(0:5)
x[x > 3]
## [1] 4 5

向量基本算數運算

向量的算術運算包括以下符號:

符號定義
+加法運算
-減法運算
*乘法運算
/除法運算
!否定運算
^指數冪運算
%%模運算
%/%商運算
%*%矩陣內積乘法
%o%矩陣外積乘法
%x%矩陣Kronecker乘法
%in%配對運算

下面是例子:

1 + 1 # 加法
## [1] 2
2 - 1 # 減法
## [1] 1
2 * 2 # 乘法
## [1] 4
6 / 3 # 除法
## [1] 2
!TRUE # 否定
## [1] FALSE
2 ^ 3 # 指數冪
## [1] 8
6 %% 4 # 取模
## [1] 2
6 %/% 4 # 取商
## [1] 1

我這個數學廢物搞不明白什麼是矩陣的內積、外積和 Kronecker 乘法,所以高級的這些運算留到以後再補充吧。

向量關係比較操作

向量關係比較包括下列符號:

符號定義
>大於
<小於
==恆等於
!=不等於
>=大於等於
<=小於等於

這些同其他的程式設計語言基本相同。看例子:

2 > 1
## [1] TRUE
2 < 1
## [1] FALSE
3 == 3
## [1] TRUE
3 != 3
## [1] FALSE
4 >= 3
## [1] TRUE
4 <= 3
## [1] FALSE

向量的邏輯操作

向量的邏輯操作包括下列符號:

符號定義
&, &&邏輯與
|, ||邏輯或
!邏輯非
xor邏輯互斥

這裡和其他程式語言依然是基本相同。直接上例子:

1 > 0 && 3 > 1
## [1] TRUE
1 > 0 || 3 < 0
## [1] TRUE
!TRUE
## [1] FALSE
x <- c(12, 24, 34)
y <- c(11, 36, 32)
xor((x - 12 > 0), (y - 10 > 0))
## [1] TRUE FALSE FALSE

這裡特別講一下互斥這個東西。這個東西叫“一身反骨”。當兩邊的算式都為 TRUE 或都為 FALSE 時,運算結果為 FALSE,而當兩邊的運算結果一個是 TRUE 一個是 FALSE 時,運算結果是 TRUE。即判斷兩個邏輯表達式結果是否不相同。

遺失值

遺失值通常用 NA 來表示。NaN 表示非數值結果。NULL 則表示空結果(物件長度為 0)。

遺失值的判斷使用 is.na() 函式,is.nan() 可以判斷元素是否是非數值。

移除遺失值則使用 na.omit()na.fail()na.exclude()na.action() 等函式。最常用的是 complete.cases() 函式。使用這個函式可以批量移除向量中的遺失值。需要注意的是, complete.cases() 本質上返回一個 logic 類型的向量,用以表示目標向量中每一個值是否是遺失值。需要配合 Index 系統以進行移除。

x <- c(1, NA, 2, NA, 3)
is.na(x)
## [1] FALSE TRUE FALSE TRUE FALSE
complete.cases(x)
## [1] TRUE FALSE TRUE FALSE TRUE
x <- x[complete.cases(x)]
## 等效於 x <- x[!is.na(x)]

不難看出,complete.cases() 函式的返回值事實上等於 !is.na() 的返回值。因此在移除遺失值方面,這二者是等效的。

類別變數 Factor

名目變數和有序變數

所謂的名目變數,或稱為名目尺度或無序變數,是指向量中的元素並沒有一個序列的尺度,同一向量中的每一個元素之間並沒有典型的量化大小的差別。例如人的五根指頭,就是五根指頭而已,並沒有說誰比誰高貴。

而有序變數則是指一個向量的元素之間是有序列尺度的。類別之間有“輕重”、“大小”、“強弱”之分。比如疼痛的等級可以分為“無”、“輕”、“中”、“重”。

類別資料及類別資料的因子變數

先來了解一下什麼叫做因子變數。因子變數 Factor 按照我粗淺的理解,暫時可以將其理解為一套分類及別名系統。

比如,我們現在有一個向量,儲存了我們一個月之內每天早上吃什麼的資料。比如我們在幾號吃了麵包和牛奶,幾號吃了油條和豆漿,幾號吃了小米粥。假設我們一個月的早餐就在這三種之間做迴圈。

那麼我們的向量當然可以寫作這樣子:

breakfast <- c("麵包和牛奶", "麵包和牛奶", "油條和豆漿", "小米粥", "油條和豆漿", ...)

不難看出,如果一個月的早餐都在這三種食物中迴圈的話,那麼我們的早餐就只有這三類。

我們不妨將其分類:

breakfast.factor <- factor(breakfast)
## 輸出breakfast.factor的值:
## [1] 麵包和牛奶 麵包和牛奶 油條和豆漿 小米粥 油條和豆漿
## Levels: 小米粥 油條和豆漿 麵包和牛奶

看到了沒?factor 的意義實際上就是一個分類的、可以更改名字的向量

使用 factor() 函式來創建因子變數。該函式的定義如下:

factor(x = character(), levels, labels = levels, exclude = NA, ordered = is.ordered(x), nmax = NA)

解釋一下它的各個引數:

  • x:原始向量,通常是文字向量,如果是數值向量,則R先轉換成文字向量。
  • levels:類別水準,代表可能出現的分類
  • labels:類別水準的標記文字
  • exclude = NA:排除遺失值或某一特定值為一類別水準
  • ordered = is.ordered(x):設定因子物件類別水準的順序,仍是無序因子物件
  • nmax = NA:是否類別水準的最大數目

可是這樣子有幾個固有的問題:

  1. 書寫特別麻煩。每一個元素都是一個字串,就代表著我們要把同樣的字串寫很多遍,會超級麻煩。而且一旦哪一天寫成了錯別字,後續進行統計的難度會加大。
  2. 佔用空間比較多。字串在記憶體中所佔的空間比較大,會比較浪費。

鑑於此,我們試想一下有沒有更加合理的方法。當然有。比如我們可以搞一個密碼本,讓數字 1 代表麵包和牛奶,數字 2 代表油條和豆漿,數字 3 代表小米粥。這樣子我們就只需要記錄數字,輸出的時候轉換到字串就好了。

那麼這樣子,我們就可以給三個分類別名

breakfast <- c(1, 1, 2, 3, 2, ...) # 定義記錄值
breakfast.factor <- factor(breakfast, levels = c(1, 2, 3), labels = c("麵包和牛奶", "油條和豆漿", "小米粥"))
## 輸出 breakfast.factor 的值
## [1] 麵包和牛奶 麵包和牛奶 油條和豆漿 小米粥 油條和豆漿
## Levels: 麵包和牛奶 油條和豆漿 小米粥

我們可以看到在這時候,就會自動把我們的記錄值按照密碼本轉換成實際要的字串。其中,levels 引數的向量元素和 labels 是一一對應的。並且 factor 儲存的仍然是之前的數字,而不是 labels 裡面的字串

可以使用 levels() 函式來修改 level。

重新設定類無需因子的參照水準

在統計模型中常使用類別變數作為解釋變數,常常必須令無序因子物件或類別變數的某一個類別水準為參照水準(reference level),以便建構類別型解釋變數內不同類別水準的對照比較(contrast comparison)。 使用函式 relevel(),可以改變無序因子類別水準的參考水準。

breakfast <- c(1, 1, 2, 3, 2, ...) # 定義記錄值
breakfast.factor <- factor(breakfast, levels = c(1, 2, 3), labels = c("麵包和牛奶", "油條和豆漿", "小米粥"))
relevel(breakfast.factor, ref = 2) # 將2作為參考水準

總之,當你有一大堆資料需要分類整理的時候,factor 可能是一個好東西。

[R Lang] R Lang 與高級醫學統計學(2)
https://blog.kynix.tw/posts/1731058866777/
作者
Adrian Chen
建檔時間
2024 年 4 月 8 日
協議
BY-NC-SA 4.0
姓名標示-非商業性-相同方式分享 4.0 國際