R的数据类型与相应运算

  • 11 R矩阵和数组
  • 11.1 R矩阵
  • 11.2 矩阵子集
  • 11.3 ``cbind()`` 和 ``rbind()`` 函数
  • 11.4 矩阵运算
  • 11.4.1 四则运算
  • 11.4.2 矩阵乘法
  • 11.4.3 向量与矩阵相乘
  • 11.4.4 内积
  • 11.4.5 外积
  • 11.5 逆矩阵与线性方程组求解
  • 11.6 ``apply()`` 函数
  • 11.7 多维数组



(学习资料参考北京大学李东风老师《R语言教程》)

11 R矩阵和数组

11.1 R矩阵

矩阵用matrix函数定义,实际存储成一个向量,根据保存的行数和列数对应到矩阵的元素, 存储次序为按列存储。 定义如:

A <- matrix(11:16, nrow=3, ncol=2); print(A)

会生成一个由数字11-16组成,3行2列的矩阵,如下:

R语言 nnet函数用法_多维数组


matrix() 函数把矩阵元素以一个向量的形式输入, 用 nrowncol 规定行数和列数,向量元素填入矩阵的缺省次序是按列填入, 用 byrow=TRUE 选项可以转换成按行填入。

nrow()ncol() 函数可以访问矩阵的行数和列数,如:

nrow(A)
ncol(A)

R语言 nnet函数用法_多维数组_02


矩阵有一个 dim 属性,内容是两个元素的向量, 两个元素分别为矩阵的行数和列数。dim 属性可以用 dim() 函数访问。如:

attributes(A)

就可以得到矩阵A的行数和列数

R语言 nnet函数用法_R语言 nnet函数用法_03


同样,dim属性也可以直接用dim函数:

dim(A)

R语言 nnet函数用法_多维数组_04


函数 t(A) 可以返回矩阵A的转置。

11.2 矩阵子集

A[1,] 取出A的第一行,变成一个普通向量。 用 A[,1] 取出A的第一列,变成一个普通向量。 用 A[c(1,3),1:2] 取出指定行、列对应的子矩阵。 如:

A[1,]
A[,1]
A[c(1,3), 1:2]

R语言 nnet函数用法_多维数组_05


colnames() 函数可以给矩阵每列命名, 也可以访问矩阵列名, 用 rownames() 函数可以给矩阵每行命名, 也可以访问矩阵行名。如:

colnames(A) <- c('X', 'Y')
rownames(A) <- c('a', 'b', 'c')
A

R语言 nnet函数用法_R语言 nnet函数用法_06


有了列名、行名后,矩阵下标可以用字符型向量, 如:

A[,'Y']
A['b',]

分别得到Y列和b行,结果如下:

R语言 nnet函数用法_R语言 nnet函数用法_07


ps.这里要注意,得到的结果都是行,但是实际上你要知道自己求的是行还是列。

注意在对矩阵取子集时, 如果取出的子集仅有一行或仅有一列, 结果就不再是矩阵而是变成了R向量, R向量既不是行向量也不是列向量。 如果想避免这样的规则起作用, 需要在方括号下标中加选项drop=FALSE, 如:

A[,1,drop=FALSE]

R语言 nnet函数用法_R语言 nnet函数用法_08


这里得到了矩阵A的第一列(X列),作为列向量取出, 所谓列向量实际是列数等于1的矩阵。 如果用常量作为下标, 其结果维数是确定的,不会出问题; 如果用表达式作为下标, 则表达式选出零个、一个、多个下标, 结果维数会有不同, 加 drop=FALSE 则是安全的做法。

R语言 nnet函数用法_矩阵乘法_09


下面试一下这个,从矩阵A中取出第1、3、5位,因为元素的保存次序是按列填入, 所以, 也可以向对一个向量取子集那样, 仅用一个正整数向量的矩阵取子集。

A[c(1,3,5)]

得到如下结果:

R语言 nnet函数用法_访问矩阵_10

为了挑选矩阵的任意元素组成的子集而不是子矩阵, 可以用一个两列的矩阵作为下标, 矩阵的每行的两个元素分别指定一个元素的行号和列号。 如:

ind <- matrix(c(1,1, 2,2, 3,2), ncol=2, byrow=TRUE)
A
ind

输出结果如下,得到A矩阵和ind矩阵:

R语言 nnet函数用法_多维数组_11


c(A)A[] 返回矩阵A的所有元素。可以看出,从c(A)返回的是一个向量,A[]返回的是一个矩阵。

R语言 nnet函数用法_访问矩阵_12


如果要修改矩阵A的所有元素, 可以对 A[] 赋值,赋值举例如下:

R语言 nnet函数用法_矩阵乘法_13

11.3 cbind()rbind() 函数

x 是向量,cbind(x)x 变成列向量, 即列数为1的矩阵, rbind(x)x 变成行向量。

x1, x2, x3是等长的向量, cbind(x1, x2, x3) 把它们看成列向量并在一起组成一个矩阵。 cbind()的自变量可以同时包含向量与矩阵,向量的长度必须与矩阵行数相等。 如:

cbind(c(1,2), c(3,4), c(5,6))

把三个向量当做列向量,组成一个3列2行的矩阵:

R语言 nnet函数用法_矩阵乘法_14


再看一个当做行向量的,组成一个3行2列的矩阵:

R语言 nnet函数用法_R语言 nnet函数用法_15


可以在现成的矩阵加一列(或一行):

cbind(A, c(1,-1,10))

R语言 nnet函数用法_R语言 nnet函数用法_16

11.4 矩阵运算

11.4.1 四则运算

与加减法线性代数中矩阵的加减法是一样的。
对两个同形状的矩阵, 用*表示两个矩阵对应元素相乘(注意这不是线性代数中的矩阵乘法), 用/表示两个矩阵对应元素相除。

11.4.2 矩阵乘法

%*% 表示矩阵乘法而不是用 * 表示, 注意矩阵乘法要求左边的矩阵的列数等于右边的矩阵的行数。 如:

A、B矩阵如下:

R语言 nnet函数用法_多维数组_17


则A、B相乘结果如下:

R语言 nnet函数用法_矩阵乘法_18

11.4.3 向量与矩阵相乘

矩阵与向量进行乘法运算时, 向量按需要解释成列向量或行向量。 当向量左乘矩阵时,看成行向量; 当向量右乘矩阵时,看成列向量。 如:

c(1,1) %*% B

这里的矩阵B与上面相同,

R语言 nnet函数用法_矩阵乘法_19


再看

B %*% c(1,1)

R语言 nnet函数用法_R语言 nnet函数用法_20


可以对比一下以上两个结果。

11.4.4 内积

直接看李东风教程内容

11.4.5 外积

11.5 逆矩阵与线性方程组求解

solve(A) 求A的逆矩阵,如:

solve(B)

R语言 nnet函数用法_R语言 nnet函数用法_21

11.6 apply() 函数

  1. apply(A, 2, FUN) 把矩阵A的每一列分别输入到函数FUN中, 得到对应于每一列的结果,如:
D <- matrix(c(6,2,3,5,4,1), nrow=3, ncol=2); D
apply(D, 2, sum)

R语言 nnet函数用法_多维数组_22

  1. apply(A, 1, FUN) 把矩阵A的每一行分别输入到函数FUN中, 得到与每一行对应的结果,如:
apply(D, 1, mean)

R语言 nnet函数用法_访问矩阵_23

  1. 如果函数FUN返回多个结果, 则apply(A, 2, FUN)结果为矩阵, 矩阵的每一列是输入矩阵相应列输入到FUN的结果, 结果列数等于A的列数。
  2. 如果函数FUN返回多个结果, 为了对每行计算FUN的结果, 结果存入一个与输入的矩阵行数相同的矩阵, 应该用t(apply(A, 1, FUN))的形式。

11.7 多维数组

多维数组的一般定义语法为

数组名 <- array(数组元素, 
  dim=c(第一下标个数, 第二下标个数, ..., 第s下标个数))

举例一个三维数组定义:

ara <- array(1:24, dim=c(2,3,4)); ara

结果如下:

R语言 nnet函数用法_多维数组_24

多维数组在取子集时如果某一维下标是标量, 则结果维数会减少, 可以在方括号内用drop=FALSE选项避免这样的规则发生作用。

类似于矩阵, 多维数组可以用一个矩阵作为下标, 如果是三维数组,矩阵就需要有3列, 四维数组需要用4列矩阵。 下标矩阵的每行对应于一个数组元素。