矩陣和數(shù)組是向量的兩種特例
矩陣在 R 中是按列(column)存儲的,但是通過設(shè)置 matrix 的參數(shù) byrow 為 TRUE 可以將矩陣元素按照行排列,矩陣本身仍是按列存儲的。
> y <- matrix(c(1,2,3,4,5,6),nrow=2)
> y
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
> y <- matrix(c(1,2,3,4,5,6),nrow=2,byrow=T)
> y
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
可以對一個(gè)矩陣的子矩陣索引賦值:
> y
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
> y[c(1,3),]
[,1] [,2]
[1,] 1 4
[2,] 3 6
> y[c(1,3),] <- matrix(c(1,1,8,12),nrow=2)
> y
[,1] [,2]
[1,] 1 8
[2,] 2 5
[3,] 1 12
對向量的負(fù)索引可以排除元素(類似取反),對矩陣同樣有效:
> y
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
> y[-2,]
[,1] [,2]
[1,] 1 4
[2,] 3 6
矩陣也可以用類似向量篩選的方法進(jìn)行篩選:
> x
[,1] [,2]
[1,] 1 2
[2,] 2 3
[3,] 3 4
> x[x[,2]>=3,]
[,1] [,2]
[1,] 2 3
[2,] 3 4
apply() 函數(shù)
apply() 函數(shù)的一般形式為:
apply(m, dimcode, f, fargs)
m 為矩陣
dimcode 為維度編號,1 代表對每一行應(yīng)用 f 函數(shù),2 代表對每一列應(yīng)用 f 函數(shù)。
f 為函數(shù)
fargs 為函數(shù)的可選參數(shù)集。
使用 apply() 函數(shù)可以讓程序更加緊湊易讀,同時(shí)避免循環(huán)語句可能產(chǎn)生的 bug。
增加或刪除矩陣的行和列
嚴(yán)格來說,矩陣的長度和維度是固定的,不能刪除或增加行和列,但可以通過為矩陣重新賦值達(dá)到相同的效果。
函數(shù) rbind() 按行組合,cbind() 按列組合,可以為矩陣增加行和列:
> z
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 2 1 0
[3,] 3 0 1
[4,] 4 0 0
> one
[1] 1 1 1 1
> two
[1] 2 2 2
> cbind(one, z)
one
[1,] 1 1 1 1
[2,] 1 2 1 0
[3,] 1 3 0 1
[4,] 1 4 0 0
> rbind(two,z)
[,1] [,2] [,3]
two 2 2 2
1 1 1
2 1 0
3 0 1
4 0 0
使用 rbind 和 cbind 會生成新的矩陣,如果在循環(huán)中頻繁生成新矩陣,是會很耗時(shí)的,最好一開始定義好一個(gè)大矩陣,每次循環(huán)時(shí)逐行或逐列進(jìn)行賦值,以避免每次循環(huán)時(shí)進(jìn)行耗時(shí)的矩陣內(nèi)存分配。
向量與矩陣的差異
矩陣比向量多了兩個(gè)屬性,行數(shù)和列數(shù):
> z <- matrix(1:8,nrow=4)
> z
[,1] [,2]
[1,] 1 5
[2,] 2 6
[3,] 3 7
[4,] 4 8
> length(z)
[1] 8
> typeof(z)
[1] "integer"
> class(z)
[1] "matrix"
> attributes(z)
$dim
[1] 4 2
> dim(z)
[1] 4 2
> nrow(z)
[1] 4
> ncol(z)
[1] 2
> nrow
function (x)
dim(x)[1L]
<bytecode: 0x2335e18>
<environment: namespace:base>
避免意外降維
對一個(gè)矩陣取子集,比如取某一行,結(jié)果會變成向量:
> z
[,1] [,2]
[1,] 1 5
[2,] 2 6
[3,] 3 7
[4,] 4 8
> r <- z[2,]
> r
[1] 2 6
> class(r)
[1] "integer"
> attributes(r)
NULL
> attributes(z)
$dim
[1] 4 2
> str(r)
int [1:2] 2 6
> str(z)
int [1:4, 1:2] 1 2 3 4 5 6 7 8
r 變成了向量,在某些矩陣運(yùn)算是可能產(chǎn)生錯(cuò)誤,為了避免意外降維可以使用 drop 參數(shù):
> r <- z[2,, drop=FALSE]
> r
[,1] [,2]
[1,] 2 6
> dim(r)
[1] 1 2
這時(shí) r 是一個(gè) 1 x 2 的矩陣,而不是向量。
對原本就是向量的對象,可以用 as.matrix() 轉(zhuǎn)化為矩陣:
> u
[1] 1 2 3
> v <- as.matrix(u)
> attributes(u)
NULL
> attributes(v)
$dim
[1] 3 1
矩陣的行和列命名問題
訪問矩陣元素最直接的方法是通過行號和列號,但是也可以用行名和列名,在分析某些數(shù)據(jù)時(shí)很有用,colnames() 和 rownames() 函數(shù)。
> z
[,1] [,2]
[1,] 1 3
[2,] 2 4
> colnames(z)
NULL
> colnames(z) <- c('a','b')
> z
a b
[1,] 1 3
[2,] 2 4
> colnames(z)
[1] "a" "b"
> z[,'a']
[1] 1 2
高維數(shù)組
矩陣只有行和列兩個(gè)維度,舉個(gè)例子,學(xué)生成績,有三個(gè)學(xué)生,考試分兩部分,考試成績每一行代表一個(gè)學(xué)生,第一個(gè)學(xué)生兩部分考試得分分別是46和30:
> firsttest
[,1] [,2]
[1,] 46 30
[2,] 21 25
[3,] 50 50
如果還有第二次考試,成績?nèi)缦拢?/p>
> secondtest
[,1] [,2]
[1,] 46 43
[2,] 41 35
[3,] 50 50
現(xiàn)在把兩次考試的成績合并到一個(gè)數(shù)據(jù)結(jié)構(gòu)中,命名為 tests,這種數(shù)據(jù)結(jié)構(gòu)就是數(shù)組。用 array() 函數(shù)創(chuàng)建這個(gè)數(shù)據(jù)結(jié)構(gòu):
> tests <- array(data=c(firsttest,secondtest), dim=c(3,2,2))
> tests
, , 1
[,1] [,2]
[1,] 46 30
[2,] 21 25
[3,] 50 50
, , 2
[,1] [,2]
[1,] 46 43
[2,] 41 35
[3,] 50 50
> attributes(tests)
$dim
[1] 3 2 2
dim=c(3,2,2) 是指這個(gè)數(shù)據(jù)有兩層,每層有三行兩列。
tests 中每一個(gè)元素都有三個(gè)下標(biāo),比矩陣多一個(gè),三個(gè)下標(biāo)順序與 $dim 中三個(gè)元素相同。例如第 3 個(gè)學(xué)生在第 1 次考試的第 2 部分得分:
> tests[3,2,1]
[1] 50
兩個(gè)矩陣可以合并為一個(gè)三維數(shù)組,兩個(gè)或者多個(gè)三維數(shù)組可以合并成一個(gè)四維數(shù)組。
把理想運(yùn)用到真實(shí)的事物上,便有了文明。