“ 矩阵是可以看作一种特殊的向量的,它比向量多了两个附加属性,行数和列数,因此让它的复杂程度获得了提高。 ”
向量作为R中的一种非常基础的数据类型,大家通过过去的学习一定已经彻底的掌握了。但是,这个世界上的数据是复杂多变的,我们只使用向量是无法表示更加复杂的数据情况。
我们在线性代数课上学过一种数学概念,矩阵。这个概念在为了统计学家开发的R语言中同样适用,并且只需要在基础环境中,我们可以具有很多对矩阵的操作方法。
( 由于R其实处理数据框较多,矩阵并不会讲很多的东西,如果非要使用矩阵,我其实还是更推荐去隔壁Python学习np和scipy )
任何数据类型学习的开始都是如何得到它,也就是如何创建它。矩阵也不例外,我们首要的 创建方式就是直接使用matrix函数进行创建 。而且其实说是创建矩阵,我们其实是在把一个向量转化为矩阵,
上面就是最基本的创建矩阵的方法了。我们 需要给matrix一个向量 (其实矩阵也可以,不过就会让你产生一些奇奇怪怪的误导,后面讲解了矩阵转向量的时候你就明白了),这个向量的内容就会成为创建的矩阵的内容。
然后跟着需要 指定你想创建的行数或者列数 ,这两个只需要指定其一即可,R会给我们计算另一个数字是几的,这样,我们就创建好了一个矩阵。
但是我们可以发现一个问题,我们创 建的矩阵是竖着一排排放的,这个叫做,****列优先原则 ,我们也可以通过指定参数 byrow,来让矩阵变成行优先 的
这就是行优先矩阵了,存储的内容都是一样的,就是行列优先顺序不同。
到这里你可能就会问了,R是不是只能创建方阵呢,普通的矩阵能不能创建呢?那当然可以了
我本人是习惯列优先进行存储的,所以我一般不指定byrow参数。
任何一种数据类型,我们对它最优先的操作学习,都是索引操作。任何一种结构的数据,我们存储它的目的都是为了使用,所以学习如果取到它的值,是非常重要的事情。
对矩阵的基本索引方式和向量非常相似,如果不了解向量的直接索引,布尔索引和连续索引,请看
由于有了上面的基础,所以我们先索引点简单的,然后做两个不一样的案例。矩阵和向量最大的区别再与矩阵具有两个维度,索引的时候需要两个位置
这里停一下,我们取第一行的所有列就已经是不同了,要注意, 当我们想取某一行的所有列,或者某列的所有行,或者当你想取所有的时候,把位置空出来 ,R就会自动给你取到所有。
说完了上面的,下面就都非常简单了
大家尤其要注意最后一种,取前两行和后两列的操作,很多时候这是非常有用的步骤,会减少你使用循环,提高程序的运行速度。
讲解完了索引,我们来讲一下如何矩阵的内容以及删除矩阵的行列。
其实修改特定位置的值非常简单,我们都已经找到了,修改就是一瞬间的事情,
除了单个值的修改,我们 还可以对索引到的行和列进行修改 ,一般来说,我们会直接把要修改的结果放进向量中,然后进行修改,但是如果修改的值不够长,也是可以操作的,如下
如果你对上面的内容表示有些困惑,那么你应该回忆一下,
这里有着你需要了解的一切。
最后讲解如何删除矩阵的行列,这里的操作也和向量是一样的,具体请回顾
本文的全部内容就到此结束了,这篇文章讲解了 最最基本的矩阵创建方法,以及对矩阵进行索引的操作,加上修改矩阵元素和删除矩阵的列等等 ,这些都是使用矩阵的基础知识,需要彻底掌握,才能在矩阵的使用中得心应手。
下一篇文章将会介绍矩阵维度,矩阵转化为向量以及矩阵的各种运算,矩阵的转置等内容。
R语言数组和矩阵1 数组
数组可以看成一个由递增下标表示的数据项的集合,例如数值。
数组的生成
如果一个向量需要在R中以数组的方式被处理,则必须含有一个维数向量作为它的dim属性。
维度向量由dim()指定,例如,z是一个由1500个元素组成的向量。下面的赋值语句
>dim(z) <- c(3,5,100)使它具有dim属性,并且将被当作一个3X5X100的数组进行处理。 c(3,5,100) 就是他的维度向量。
还可以用到像matrix()和array()这样的函数来赋值。比如
>array(1:20, dim=c(4,5))
>matrix(1:24, 3,4)
数据向量中的值被赋给数组中的值时,将遵循与FORTRAN相同的原则"主列顺序",即第一个下标变化的最快,最后的下标变化最慢。
数组的运算
数组可以在算数表达式中使用,结果也是一个数组,这个数组由数据向量逐个元素的运算后组成,通常参与运算的对象应当具有相同的dim属性。
2 数组的索引和数组的子块
数组中的单个元素可以通过下标来指定,下标由逗号分隔,写在括号内。
我们可以通过在下标的位置给出一个索引向量来指定一个数组的子块,不过如果在任何一个索引位置上给出空的索引向量,则相当于选取了这个下标的全部范围。
如a[2,,],a[,3,]等
3 索引数组
除了索引向量,还可以使用索引数组来指定数组的某些元素。
例如:有4X5的数组a,若要得到a中的a[1,3], a[2,2] 和a[3,1]这三个元素,可以生成索引向量i,然后用a[i]得到它们。
>a <- array(1:20,dim=c(4,5)) # Generate a 4 by 5 array.
>i <- array(c(1:3,3:1),dim=c(3,2))
>i
[,1] [,2]
[1,] 1 3
[2,] 2 2
[3,] 3 1
>a[i]
[1] 9 6 3
>a[i] <- 0 # 将这三个元素用0替换。
4 向量,数组的混合运算
表达式从左到右被扫描;
参与运算的任意对象如果大小不足,都将被重复使用直到与其他参与运算的对象等长;
当较短的向量和数组在运算中相遇时,所有的数组必须具有相同的dim属性,否则返回一个错误;
如果有任意参与运算的向量比参与运算的矩阵或数组长,将会产生错误;
如果数组结构正常声称,并且没有错误或者强制转换被应用于向量上,那么得到的结果与参与运算的数组具有相同的dim属性。
5 矩阵的运算
构建分区矩阵:cbind()和rbind(),cbind()按照水平方向,或者说按列的方式将矩阵连接到一起。rbind()按照垂直的方向,或者说按行的方式将矩阵连接到一起。
外积:操作符是%o%:
>ab <- a %o% b 或者
>ab <- outer(a, b, "*")
其中的乘法操作可以由任意一个双变量的函数替代。
广义转置:函数t(A),或aperm(A, c(2,1));
获取行数/列数:nrow(A)和ncol(A)分别返回矩阵A的行数和列数。
矩阵乘法:操作符为%*%;
交叉乘积(cross product):crossprod(X,Y)等同于t(X) %*% y,crossprod(X)等价于crossprod(X, X);
diag(v):如果v是向量,diag(v)返回一个由v的元素为对角元素的对角矩阵。
如果v为矩阵,diag(v)返回一个由v主对角元素组成的向量。
如果v只是一个数值,那么diag(v)是一个vXv的单位矩阵。
特征值和特征向量:eigen(Sm)。这个函数的结果是由名为values和vectors的两部分组成的列表。如果只是需要特征值:eigen(Sm)$values
最小二乘拟合即QR分解:lsfit(), qr()。
强制转换为向量:as.vector(),或者直接c().
这是最后一篇讲解有关矩阵操作的博客,介绍有关矩阵的函数,主要有 rowSums() , colSums() , rowMeans() , colMeans() , apply() , rbind() , cbind() , row() , col() , rowsum() , aggregate() , sweep() , max.col() 。
下面通过例子来了解这些函数的用法:
我们知道,通过下标索引 [i, j] 可以访问矩阵的某一部分,索引如果没有提供意味着“所有行”或“所有列”。来看个例子,比如:
在R中,可以用一些特殊的函数来进行矩阵的行、列计算。来看些例子:
上述矩阵的行、列计算,还可以使用 apply() 函数来实现。 apply() 函数的原型为 apply(X, MARGIN, FUN, ...) ,其中: X 为矩阵或数组; MARGIN 用来指定是对行运算还是对列运算, MARGIN=1 表示对行运算, MARGIN=2 表示对列运算; FUN 用来指定运算函数; ... 用来指定 FUN 中需要的其它参数。来看些例子:
用 apply() 函数来实现上面的例子
apply() 函数功能很强大,我们可以对矩阵的行或列进行其它运算,例如:
如果矩阵存在 NA 值,可通过设置 na.rm=TRUE 来忽略 NA 值,然后再计算。比如:
甚至我们还可以自定义运算函数,来看个例子:
在R中, rbind() 和 cbind() 函数可分别为矩阵添加行和列,来看一个例子:
在R中, row() 和 col() 函数将分别返回元素的行和列下标矩阵,来看个例子:
通过这两个函数,可以获取矩阵的对角元素以及上下三角矩阵,例如:
有时,你可能需要对每行进行分组,然后组内每列求和。在R中可以用 rowsum() 函数来解决,而且效率也非常高。先看个例子:
你也可以用 aggregate() 函数获得类似结果:
有人就会问“为啥没有列分组求和的操作?”,其实你可以先将矩阵转置,然后行分组求和;这两步就等同于列分组求和。
sweep() 函数的原型为 sweep(x, MARGIN, STATS, FUN = "-", check.margin = TRUE, ...) ,其中: x 为矩阵或数组; MARGIN 用来指定是对行运算还是对列运算, MARGIN=1 表示对行运算, MARGIN=2 表示对列运算; STATS 表示想要清除的统计量; FUN 用来指定运算函数,默认为减法 - ; check.margin 用来核实 x 的维度是否与 STATS 的匹配,如果事先知道它们匹配的话,将其设为 FALSE 将提高运算速度; ... 用来指定 FUN 中需要的其它参数。来看些例子:
事实上,通过改变 FUN 参数的具体形式或自定义函数, sweep() 函数可以实现很多不同操作,这里就不细讲了。
max.col() 函数返回矩阵每行最大值所在的列位置(即列下标),其原型为 max.col(m, ties.method = c("random", "first", "last")) ,其中: m 为矩阵;当存在多个最大值时, ties.method 指定用哪种方式来处理这种情况,默认为"random"(随机),"first"指使用第一个最大值,"last"指使用最后一个最大值。来看个官网例子:
我们也可以结合 apply() 和 which.max() 函数来实现 max.col(mm, 'first') 。看个例子,
R矩阵的最后一部分内容就讲到这。
如若有遗漏,后期将会添加至本博客。