這篇文章講R Lang的基本物件類型——向量(vector)。
向量的基本概念
向量(vector)是指具有相同模式(mode)的元素組成的集合。其實就是其他程式語言中“數組”的概念。作為一門專攻統計學的程式設計語言,R Lang的基本運算單位並不是其他語言的單一變數,而是變數的群體。這個群體的最小體現就是向量。在R Lang中,單一數值的變數可以被看作長度為1的向量。
向量並不具有維度。例如c(1, 2, 3)
可以看作
向量的基本資料類型(模式)
可以透過class()
函式來查看一個變數的模式,透過is.mode()
函式來判斷變數是否是某種模式。
1 | class(x) # 查看變數x的模式 |
基本模式有下面幾種:
numeric
數值型,也即其他語言的“浮點型”,包含單精度浮點型(single)和雙精度浮點型(double)。
1 | pi <- 3.14 |
integer
整數型,需要在值後面加上“L”,否則解釋器講自動將其歸為numeric類型。整數性可以算作數值型的一個特例,因此使用is.numeric()
函式仍然返回為TRUE。
1 | x <- 2L |
logical
布林型,取值為“TRUE(T)”或“FALSE(F)”,或者用1和0分別代表T和F。
1 | x <- TRUE |
complex
複數型
1 | x <- 3 + 5i |
character
文字或字串。在R Lang中並未區分字元和字串這兩個概念。事實上一個字元就可以看作只包含一個字元的字串。在R Lang中統一使用雙引號。
1 | x <- "Hello, world." |
向量的產生和運算
使用c()
函式即可產生一個向量。
1 | x <- c(1, 2, 3) |
向量的元素命名
向量中的每一個元素都可以進行命名。可以在定義的時候直接命名或者在後期使用names()
函式來進行命名。
1 | x <- c( |
向量的下標與索引
類似於其他程式語言中數組可以透過下標Index訪問,向量也一樣可以。但是在R Lang中向量的下標系統相比其他語言更加強大。R Lang的下標支援正整數、負整數、文字、字串、邏輯向量。
正整數
即第幾個元素。於其他程式語言相同。但是特別注意,R Lang中下標從1開始算起,而不是我們熟悉的從0開始。
1 | x <- c(0:5) # 用:來定義從0~5 |
負整數
返回原向量中排除負整數後的向量結果。
1 | x <- c(0:5) |
文字
如果給向量元素命名過,我們就可以使用字串作為Index來查找對應的元素。
1 | x <- c(0:5) |
邏輯向量
直接將邏輯向量作為Index,以從目標向量中篩選出符合邏輯的子向量。
1 | x <- c(0:5) |
向量基本算數運算
向量的算術運算包括以下符號:
符號 | 定義 |
---|---|
+ | 加法運算 |
- | 減法運算 |
* | 乘法運算 |
/ | 除法運算 |
! | 否定運算 |
^ | 指數冪運算 |
%% | 模運算 |
%/% | 商運算 |
%*% | 矩陣內積乘法 |
%o% | 矩陣外積乘法 |
%x% | 矩陣Kronecker乘法 |
%in% | 配對運算 |
下面是例子:
1 | 1 + 1 # 加法 |
我這個數學廢物搞不明白什麼是矩陣的內積、外積和Kronecker乘法,所以高級的這些運算留到以後再補充吧。
向量關係比較操作
向量關係比較包括下列符號:
符號 | 定義 |
---|---|
> | 大於 |
< | 小於 |
== | 恆等於 |
!= | 不等於 |
>= | 大於等於 |
<= | 小於等於 |
這些同其他的程式設計語言基本相同。看例子:
1 | 2 > 1 |
向量的邏輯操作
向量的邏輯操作包括下列符號:
符號 | 定義 | |||
---|---|---|---|---|
&, && | 邏輯與 | |||
\ | , \ | \ | 邏輯或 | |
! | 邏輯非 | |||
xor | 邏輯互斥 |
這裡和其他程式語言依然是基本相同。直接上例子:
1 | 1 > 0 && 3 > 1 |
這裡特別講一下互斥這個東西。這個東西叫“一身反骨”。當兩邊的算式都為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系統以進行移除。
1 | x <- c(1, NA, 2, NA, 3) |
不難看出,complete.cases()
函式的返回值事實上等於!is.na()
的返回值。因此在移除遺失值方面,這二者是等效的。
類別變數 Factor
名目變數和有序變數
所謂的名目變數,或稱為名目尺度或無序變數,是指向量中的元素並沒有一個序列的尺度,同一向量中的每一個元素之間並沒有典型的量化大小的差別。例如人的五根指頭,就是五根指頭而已,並沒有說誰比誰高貴。
而有序變數則是指一個向量的元素之間是有序列尺度的。類別之間有“輕重”、“大小”、“強弱”之分。比如疼痛的等級可以分為“無”、“輕”、“中”、“重”。
類別資料及類別資料的因子變數
先來了解一下什麼叫做因子變數。因子變數Factor按照我粗淺的理解,暫時可以將其理解為一套分類及別名系統。
比如,我們現在有一個向量,儲存了我們一個月之內每天早上吃什麼的資料。比如我們在幾號吃了麵包和牛奶,幾號吃了油條和豆漿,幾號吃了小米粥。假設我們一個月的早餐就在這三種之間做迴圈。
那麼我們的向量當然可以寫作這樣子:
1 | breakfast <- c("麵包和牛奶", "麵包和牛奶", "油條和豆漿", "小米粥", "油條和豆漿", ...) |
不難看出,如果一個月的早餐都在這三種食物中迴圈的話,那麼我們的早餐就只有這三類。
我們不妨將其分類:
1 | breakfast.factor <- factor(breakfast) |
看到了沒?factor的意義實際上就是一個分類的、可以更改名字的向量。
使用factor()
函式來創建因子變數。該函式的定義如下:
1 | 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代表油條和豆漿,數字3代表小米粥。這樣子我們就只需要記錄數字,輸出的時候轉換到字串就好了。
那麼這樣子,我們就可以給三個分類別名。
1 | breakfast <- c(1, 1, 2, 3, 2, ...) # 定義記錄值 |
我們可以看到在這時候,就會自動把我們的記錄值按照密碼本轉換成實際要的字串。其中,levels引數的向量元素和labels是一一對應的。並且factor儲存的仍然是之前的數字,而不是labels裡面的字串。
可以使用levels()
函式來修改level。
重新設定類無需因子的參照水準
在統計模型中常使用類別變數作為解釋變數,常常必須令無序因子物件或類別變數的某一個類別水準為參照水準 (reference level),以便建構類別型解釋變數內不同類別水準的對照比較 (contrast comparison)。 使用函式relevel()
,可以改變無序因子類別水準的參考水準。
1 | breakfast <- c(1, 1, 2, 3, 2, ...) # 定義記錄值 |
總之,當你有一大堆資料需要分類整理的時候,factor可能是一個好東西。