vlambda博客
学习文章列表

【R语言学习】004 向量、矩阵、数组


【R语言学习】  004 向量、矩阵、数组

最终梦想:将R当成一个绘图软件来使用

本章目标:能按照要求建立相应序列、矩阵、数组。

                会用R进行矩阵运算

这章有点长,好学的同志一定能耐心看下去(我在努力让推文赶上老师进度)

一、向量

先说一个小技巧,在Rstudio里,同时按alt键和-键,能快速打出 <-
引语:
此前已经认识了逻辑型向量、字符串向量、数字向量。介绍了c函数。这一节将会介绍更多向量的操作方法。
首先介绍一个vector函数。这个函数能创建一个指定类型和长度的向量。这个向量里“什么都没有”
可以用每个类型的包装函数来创建向量来节省打字时间
> vector("complex",5)[1] 0+0i 0+0i 0+0i 0+0i 0+0i> complex(5)[1] 0+0i 0+0i 0+0i 0+0i 0+0i
> vector("logical",5)[1] FALSE FALSE FALSE FALSE FALSE> logical(5)[1] FALSE FALSE FALSE FALSE FALSE
  1. 序列

(1)seq系列

除了冒号运算符,还有几个其他函数能创建更通用的序列
首先要介绍seq函数
一个完整的seq函数是 seq(from=,to=,by(步长)= ,length.out=)
当参数length.out(输出多少个数)给定时,by会自动计算

eg:

> seq(1,5)[1] 1 2 3 4 5> seq(1:5)[1] 1 2 3 4 5> seq.int(1,5,2)[1] 1 3 5
seq.int函数创建的是等差数列。seq.int(X,Y,Z)中,X表示起始值(from),Y表示终点值(to),Z表示步长(by)。seq.int默认步长为1,当步长为1时,逗号和冒号意义相同且可以省略步长参数。
seq_len()   创建一个从1到它输入值的序列。这个函数异常的鸡肋,不如冒号简便。但是,当输入值为0的时候,情况有所不同。
> seq_len(0)integer(0)
> 1:0[1] 1 0
seq_along()创建一个从1开始长度为其输入值的序列
小应用,“逐个打印”:
> name<-c("chen01","wen02","tao03","chen04","zhuang05","han06")> for(i in seq_along(name)) print (name[i])[1] "chen01"[1] "wen02"[1] "tao03"[1] "chen04"[1] "zhuang05"[1] "han06"

(2)中括号

直接看例子吧

> vector1 <- 1:10> vector1 [-c(2,3,7)][1] 1 4 5 6 8 9 10
中括号指的是该元素的 下标 ,如果不对变量赋值,直接用中括号函数,则会出现这样的错误
> vector2[2:10]错误: 找不到对象'vector2'

2.长度

所有向量都有一个长度,在003中我们知道,它告诉我们向量包含多少元素。这一定是一个非负整数。 缺失值NA也会被记入长度。
有点容易被搞混的是 字符向量。它们长度等于字符串的个数 而非每个字符串的长度。这一点显然与C++不同。
要想知道每个字符的长度,我们可以使用 nchar函数

例子:

> string1 <- c("cwt","wct","wtzh","zhcwt")> length(string1)[1] 4> nchar(string1)[1] 3 3 4 5

3.命名

之所以要给向量元素命名,是为了让其可读性增强
有两种方法
①可以在向量创建之后,用names函数给元素添加名字
例如:
> cwt <- seq.int(1,5,length.out = 3)> names(cwt)<-c("great","handsome","politely")> cwt great handsome politely  1 3 5

②直接在创建向量的时候命名

> czh<-c("nice"=1,"handsome"=2,"wise"=3)> czh nice handsome wise  1 2 3
当然,命名的时候可以只命名部分元素。如果该元素没有得到名字,则我们使用names函数查询该向量中元素名时,该元素会返回一个空值

4.索引

(1)下标

实际上就是之前提到的“中括号”。所谓索引就是只访问向量中部分或者个别元素。在学习C++数组的时候,总是会提到下标问题。在R语言中,下标从1开始而非从0开始。
下标都是整数,如果传入的下标是分数或者小数,系统会自动向0舍入,如x[1.8],会自动将1.8舍入为1,-1.9则会舍入成-1。
超出范围的下标值会返回一个NA
以下3种索引方法都将返回相同的结果
> x<-c(1:10)^3> x [1] 1 8 27 64 125 216 343 512 729 1000> x[c(1,2,4)][1] 1 8 64> x[c(-3,-5,-6,-7,-8,-9,-10)][1] 1 8 64> x[c(TRUE,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE)][1] 1 8 64

输入的下标为负数,表示这些位置上的不显示。

正负值不能混合使用,否则会出现错误。

(2)which函数

which函数将返回逻辑向量中为true的位置

这个很方便

例子:(还是用刚刚的x)

> which(x>10)[1] 3 4 5 6 7 8 9 10> which.min(x)[1] 1> which.max(x)[1] 10

再次注意,which返回的是位置

5.循环与重复

一般教的比较着急的速成课程,会直接在讲完seq之后就开始讲rep。


先说循环:我在002当中有这样一个例子

这就是“循环”,那个warning message可以不管它

接下来看重复

说白了向量的重复就是一个rep函数的应用

rep函数简言之就是,rep(x,times=,length.out=,each,)

像seq函数那样,times之类的可以不写。times是x整体的重复次数,length.out表示结果截取前多少个元素显示,each则表示x中的单个元素重复多少遍。

例如:

> y<-seq.int(1,10,2)> rep(y,2,7,2)[1] 1 1 3 3 5 5 7

向量这节到此结束,请看下一节,矩阵和数组。



二、矩阵和数组

  1. 创建矩阵和数组

    矩阵和数组可以理解成比向量壮很多倍的兄弟

       我们此前见到的向量都是1维的,他们可以很长,但没有宽度(也就是维度)。这里的矩阵就是线性代数中的矩),是二维数组的特例。

可以使用array函数创建一个数组。为他们传入两个向量(值和维度)作为参数,当然,我们也可以给每个维度起名字(例子中随便取的)。(这个例子看不懂可以继续往下看)

在英文中,

row 是横向的,排的意思
column 是纵向的,列的意思

《学习R》的译者是个大忽悠,把这两个翻译反了,,,(就这个睿智操作浪费我一个多小时时间检查演示代码)

例如:

> three_d_array <- array(1:24,+ dim=c(4,3,2),+ dimnames = list(c("one","two","three","four"),+ c("handsome","tall","strong"),+ c("jojo","dio")+ )+ )> three_d_array, , jojo
handsome tall strongone 1 5 9two 2 6 10three 3 7 11four 4 8 12
, , dio
handsome tall strongone 13 17 21two 14 18 22three 15 19 23four 16 20 24

dimnames指维度命名。如果把2,换成3,4,又会怎样?各位可以试试。

哪里有什么不够,循环多了就够了

——鲁迅

要注意的是,维度命名要和维度个数相匹配。

创建矩阵(matrix)的语法和上面非常类似,唯一不同的是,创建矩阵不需要传递地面参数,只要指定行数或列数即可(说白了只生成一张二维的表)。nrow用来指定列数。事实上当数据总数一定时,只用设定列数即可。

例如:(做一张本人的身高体重表)

> me<- matrix(c(54,63,67,158,183,189),+ nrow=3,+ dimnames = list(+ c("2013","2016","2019"),+ c("weight/kg","height/cm")+ )+ )> me  weight/kg height/cm2013 54 1582016 63 1832019 67 189

是不是很炫酷?

当然咯,我们可以用array来构建矩阵,说白了就是构建一个二维数组。如果不相信,可以自己构建一个,然后用identical函数检验,返回值一定是TRUE。这里就不演示了。不会用identical的可以看前面的002推文。

在尝试中,无需他人告诉,我们也能发现,在创建矩阵的时候传入的值按列填充矩阵。

也可以指定参数byrow=TRUE来填充,这样可以避免让一些null值或者NA混入其中。

2.行、列、维度

刚看到第一个例子的时候,可能会有点小蒙圈,特别是看到那行dim(4,3,2)的时候,不知道4,3,2分别对应什么。

如果仔细观察,可以发现:4,对应列;3,对应行;2,对应我们称为“表”的个数。

注解到此为止。

在这里我想先谈的是length函数。

问题:一个数组的length是什么?

答:length还是原来的length,即元素个数。那么这里,我们不难理解,length=所有维度之积。

其次,我们可以通过dim函数分配一个新的维度来重塑矩阵或数组。不过这里得小心翼翼,因为这样会删除原维度的名称

当我们把nrow,ncol和dim应用于向量时,会返回NULL,

与之相对应的NROW和NCOL,则把向量当成矩阵来处理。例如:

> twc <- c(1,2,3,4,5)> ncol(twc)NULL> NCOL(twc)[1] 1> nrow(twc)NULL> NROW(twc)[1] 5

3.命名

这个还没啥好说的,dimnames、rownames、colnames,就是字面意思。

4.索引

这个,依然是下标问题。和向量一个道理。只不过要多考虑一个维度。

依然是用方括号表示索引。

而且还是老样子,四种索引方法(正整数,负整数,逻辑值,元素名

要表示所有维度,只需要把相应的下标空出来(看行空列,看列空行)

具体看例子:这里因为我懒所以用上面已经输出的me矩阵(就是身高体重那个)

me[1,]weight/kg height/cm  54 158 > #第一行的所有元素

5.合并矩阵

c函数能在拼接矩阵之前把它们转换成向量。

rbind,看字面可以明白就是“按行绑起来”,(按行合并)

cbind,“按列绑起来”(按列合并)

eg:这里依然用了之前的me矩阵,然后随便建了另一个莫名其妙的矩阵用来演示

> another_me <- matrix(+ c(108,126,134,79,96,99),+ nrow = 3,+ dimnames=list(+ c("3102","6102","9102"),+ c("konodioda","theworld")+ )+ )> c(another_me,me) [1] 108 126 134 79 96 99 54 63 67 158 183 189> cbind(another_me,me) konodioda theworld weight/kg height/cm3102 108 79 54 1586102 126 96 63 1839102 134 99 67 189> rbind(another_me,me) konodioda theworld3102 108 796102 126 969102 134 992013 54 1582016 63 1832019 67 189

6.矩阵运算

和向量运算类似,标准运算符(+-*/)对矩阵和数组同样适用,运算法则同线性代数。

特别注意,当对两个数组进行算数运算时,一些特定维度必须相等。

例如:矩阵相乘时前一个的行数要等于后一个的列数,两个数组相加时各个维度都要相等。如果连线性代数的运算规则都遵守不了,计算机是不会帮你算高代作业的

【R语言学习】004 向量、矩阵、数组t函数用来转置矩阵,但不能转置2维以上的数组

【R语言学习】004 向量、矩阵、数组矩阵的內积与外积

【R语言学习】004 向量、矩阵、数组

内积用特殊运算符%*%计算;外积用特殊运算符%o%计算


每一次,若维度的名称存在,则取第一个输入。

【R语言学习】004 向量、矩阵、数组求逆矩阵:用solve函数而不是用-1次幂


本章内容到此为止。



本章作业代码:(题目见下方照片)

注  练习4-2应是生成23*23的矩阵

#excercise 4-1> num<-c(1:20)> thenumber <- num*(num+1)/2> names(thenumber) <- c(letters[1:20])> thenumber a b c d e f g h i j k l m n  1 3 6 10 15 21 28 36 45 55 66 78 91 105  o p q r s t 120 136 153 171 190 210 ##这里是输出的> thenumber[c("a","e","i","o")] a e i o  1 15 45 120 ##这里是输出的
  #excercise 4—2 sequ001<-11:1sequ002<-0:11 x <- c(sequ001,sequ002)diag(x)##还有一种方法:diag(abs(seq.int(-11,11)))##输出结果不在这里显示因为太大了
##excercise 4-3square21 <- diag(1,ncol=21,nrow = 20)square21line0<-matrix(rep(0,1),1,ncol =21)
m<-rbind(line0,square21)mo <- rbind(square21,line0)n <- diag(abs(seq.int(-10,10)))p <- m+op+neigen((p+n))特点:大部分特征值特征向量都相等后来在csdn查了一下发现还真的只有这个不算特点的特点。。。

本期到这里结束


看在我全部手打的份上

还有琴吹紬的份上

点个关注点个在看吧

欢迎关注淏泧三千

这是一个让作者放弃王者、崩坏3、方舟、fgo、万象