MATLAB矩阵(二)


概述

在上一节中,我们介绍了如何创建一个矩阵,并且介绍了MATLAB中的一些运算符。在本节中,我们将在深入学习MATLAB中的矩阵。
本次的内容有点多,划一下重点:

  • size函数:创建矩阵和确定循环结构的循环次数
  • reshape函数:重新排列矩阵
  • sort函数:内置的sort函数比自己编写的排序更高效
  • [ ]运算符:串联矩阵最重要的步骤
  • repmat函数:重复矩阵的拼接
  • 索引:功能强大,针对性的选取数组元素

矩阵的属性

复习一下之前介绍过的MATLAB命令:(>> whos)。

功能为显示所有变量的属性。有时候我们需要根据矩阵的属性来做一些操作就需要用到矩阵的一些相关属性。常用的属性都可以通过函数来调用:size,length,isrow,numel等。

size

size函数返回矩阵的各个维度的长度,调用方法为:sz = size(A)

% size ()
% 命令行输入
A = zeros(3,4); % 先创建一个3×4的零矩阵,观察以下几个值
S = size(A)
[m,n] = size(A)
% 补充:这样写是能够让函数返回两个不同的输出参数。
% 调用函数时,系统会告诉函数有多少个输入参数和输出参数
% 函数本身则根据输入输出参数的数量决定自己的输出参数。
mm = size(A,1)
nn = size(A,2)

将以上命令输入至命令行,将得到以下输出:

% 命令行输出
S =
     3     4
% 直接调用返回一个输出参数时:
% size函数返回一个矩阵包含各个维度长度的矩阵。

m =

     3


n =

     4
% 直接调用返回两个输出参数时:
% size函数返回两个标量各自表示各个维度长度。

mm =
     3
nn =
     4
% 调用size函数时,加上想查询的具体维度,可以返回该维度上的长度
% 在这里,1指横坐标,2指纵坐标,3指竖坐标   

length

length函数返回矩阵的最长维度的长度,调用方法为:L = length(A)

% length ()
% 命令行输入
A = zeros(3,4); % 先创建一个3×4的零矩阵
S = length(A)

将以上命令输入至命令行,将得到以下输出:

% 命令行输出
S =
        4
% length 函数返回矩阵的最长维度的长度,相当于size(A)的最大值。

isrow

isrow如其名,作用就是询问矩阵是不是行向量。
同样作用的还有iscolumn确定矩阵是不是列向量,isempty确定矩阵是不是为空

% isrow ()
% 命令行输入
A = zeros(1,4); % 创建一个1×4的矩阵,观察以下几个值
S1 = isrow(A)
S2 = iscolumn(A)
S3 = isempty(A)
whos S1

将以上命令输入至命令行,将得到以下输出:

% 命令行输出
S1 =
     1

S2 =
     0

S3 =
     0
  Name      Size            Bytes  Class      Attributes
  S1        1x1                 1  logical  
% isrow 函数返回一个布尔值1或0
% 用whos命令可以看到返回的类型是logical(逻辑值非一即零,非真即假)。

numel

numel函数返回数组元素的数量,

A = zeros(3,4); % 创建一个1×4的矩阵,观察以下几个值
n = numel(A)

将以上命令输入至命令行,将得到以下输出:

% 命令行输出
n =
    12 
% 返回矩阵所有元素的个数

矩阵的排列

矩阵的另一类操作是排列,对矩阵内的元素的相对位置重新处理,(很抽象的描述,还是看看函数的功能比较容易)。常见的的函数有reshape,sort,flip,circshift等

reshape

reshape 函数顾名思义就是对矩阵重排,

A = magic(4) % 创建一个4×4的矩阵,观察以下几个值
AA = reshape(A,2,8)

将以上命令输入至命令行,将得到以下输出:

% 命令行输出
% reshape 之前
A =

    16     2     3    13
     5    11    10     8
     9     7     6    12
     4    14    15     1

% reshape 之后
AA =

    16     9     2     7     3     6    13    12
     5     4    11    14    10    15     8     1
     
% 这里又有另一个关注的点:重排的顺序,可以看到A的每一列分成了两列
% 原理:所有的矩阵在计算机中都是储存在线性空间里,实际上的顺序就是一列一列的拼接:
% 16 5 9 4 2 11 7 14 3 10 6 15 13 8 12 1
% 重排的时候仍然依照这个顺序取出。

sort

对矩阵进行排序,默认升序(从小到大)

A1 = [ 23 5 -1 4  7 0]
B1 = sort(A1)

A2 = [7 8 9; 2 4 -2; 10 2 4]
B2 = sort(A2,2) % 另一个输入参数为排序的维度
% 1指横坐标,2指纵坐标,3指竖坐标的规则仍适用
B2 = sort(A2) % 若不输入另一个参数,则默认另一个参数是1,按列排序

A3 = [ 23 5 -1 4  7 0]
B3 = sort(A3,'descend') 
% 默认情况下,sort为升序('ascend'),使用降序时,可以使用输入参数'descend'来使用降序方法

A4 = [ 23 5 -1 4  7 0]
[B,I] = sort(A4)
A(I)
% sort返回两个输出参数时,
% 第一个变量返回排序后的数组,
% 第二个变量返回排序后的数组对应原有的数组索引A(I)和B是一样的。

将以上命令输入至命令行,将得到以下输出:

A1 =
    23     5    -1     4     7     0
B1 =
    -1     0     4     5     7    23
% sort排序一维矩阵时,返回排序后的一维矩阵

A2 =
     7     8     9
     2     4    -2
    10     2     4

B2 =
     7     8     9
    -2     2     4
     2     4    10
% 另一个输入参数为2,也就是按纵坐标排序

B2 =
     2     2    -2
     7     4     4
    10     8     9
% 若不输入另一个参数,则默认另一个参数是1,按列排序
    
A3 =
    23     5    -1     4     7     0
B3 =
    23     7     5     4     0    -1
% 可以sort(A3,'descend')

A4 =
    23     5    -1     4     7     0
B =
    -1     0     4     5     7    23
I =
     3     6     4     2     5     1
ans =
    -1     0     4     5     7    23
% B为排序后的矩阵,I是一个索引(稍后会介绍索引:表示对应的关系)
% 可以看到B 和 A(I) 是完全一致的。

flip

flip就是反转矩阵的元素

A1 = [3 7 6 -1 0]
B1 = flip(A1)

A2 = [ 2 5 7;-5 3 5;0 6 5]
B2 = flip(A2)

A3 = [ 2 5 7;-5 3 5;0 6 5]
B3 = flip(A3,2)

将以上命令输入至命令行,将得到以下输出:

A1 =
     3     7     6    -1     0
B1 =
     0    -1     6     7     3
% flip函数用于快速反转一个矩阵
A2 =
     2     5     7
    -5     3     5
     0     6     5
B2 =
     0     6     5
    -5     3     5
     2     5     7
二维矩阵的反转默认按列反转
A3 =
     2     5     7
    -5     3     5
     0     6     5
B3 =
     7     5     2
     5     3    -5
     5     6     0
二维矩阵的反转也可以用flip(__,2)指定按行反转

circshift

循环移位:所有元素向后移位,超出的部分自动补回到最前面

A1 = [3 7 6 -1 0 2 8 0 ]
B1 = circshift(A1,[0,3])
% circshift(__,[m,n])表示,矩阵向下循环移动m位,矩阵向右循环移动n位

A2 = [ 1 0 0;0 0 0;0 0 0]
B2 = circshift(A2,[1,2])

将以上命令输入至命令行,将得到以下输出:

A1 =
     3     7     6    -1     0     2     8     0
B1 =
     2     8     0     3     7     6    -1     0
% circshift(__,[m,n])表示,矩阵向下循环移动m位,矩阵向右循环移动n位
A2 =
     1     0     0
     0     0     0
     0     0     0
B2 =
     0     0     0
     0     0     1
     0     0     0

拼接矩阵

拼接矩阵是另一类创建矩阵的特殊手段,需要对矩阵元素直接的关系有足够的理解。我们先介绍([ ]),再介绍类似于 repmat,cat,repelem的函数用法。

[ ]
我们将左右中括号用于创建矩阵,我们其实就是将若干个数用中括号实现了元素和矩阵的拼接。

a = [1,2]
b = [3,4] % 用来拼接
c = [a,0,b] 
d = [a;b]
e = [a,a;a,b]
% f = [a,a,a;b,b] % 这样做矩阵不匹配
g = [c;a,0,1,2]

将以上命令输入至命令行,将得到以下输出:

a =
     1     2
b =
     3     4
c =
     1     2     0     3     4
% 矩阵和数字可以混合拼接
d =
     1     2
     3     4
% 分号换行就是在列方向上拼接
e =
     1     2     1     2
     1     2     3     4
% 二维矩阵也可以拼接
g =
     1     2     0     3     4
     1     2     0     1     2
% 只要总的可以组成矩阵,矩阵可以任意拼接。

repmat

创建重复矩阵组成的拼接矩阵

A = [1,0;0,-1]
B1 = repmat(A,2)% 
B2 = repmat(A,2,3)  % 
B3 = repmat(A,[2,3])% 
% repmat(__,[m,n])和repmat(__,m,n)完全一致。

将以上命令输入至命令行,将得到以下输出:

A =
     1     0
     0    -1
B1 =
     1     0     1     0
     0    -1     0    -1
     1     0     1     0
     0    -1     0    -1
% 只传一个参数时,会在两个维度上都进行重复
B2 =
     1     0     1     0     1     0
     0    -1     0    -1     0    -1
     1     0     1     0     1     0
     0    -1     0    -1     0    -1
B3 =
     1     0     1     0     1     0
     0    -1     0    -1     0    -1
     1     0     1     0     1     0
     0    -1     0    -1     0    -1
 % repmat(__,[m,n])和repmat(__,m,n)完全一致。
 % m为在列方向重复次数,n为在行方向重复次数。

cat

cat函数是中括号的函数形式,唯一不同的地方是cat函数可以连接三维矩阵

A = [1, 2;3, 4]
B = [5, 6;7, 8]
C1 = cat(1,A,B)
C2 = cat(2,A,B)
C3 = cat(3,A,B)

将以上命令输入至命令行,将得到以下输出:

A =
     1     2
     3     4
B =
     5     6
     7     8
C1 =
     1     2
     3     4
     5     6
     7     8
% 维度一,列方向
C2 =
     1     2     5     6
     3     4     7     8
% 维度二,行方向
C3(:,:,1) =
     1     2
     3     4
C3(:,:,2) =
     5     6
     7     8
% 维度三,竖方向这样做可以创建三维矩阵

repelem

复写矩阵里的元素

A1 = [ 1 2 3]
B1 = repelem(A1,2)
% 对于一维矩阵而言,repelem(__,m)相当于每个元素都重复m次。
B2 = repelem(A1,[2 3 4])
% 如果附加的参数是一个等长度的一维矩阵,那么会以对应的频数复写元素。

A3 = [1 2; 3 4]
B3 = repelem(A3,2,3)
% 对于任意的矩阵而言都可以repelem(__,m,n),将每个元素以m×n复写

将以上命令输入至命令行,将得到以下输出

A1 =
     1     2     3
B1 =
     1     1     2     2     3     3
% 输入的第二个参数是2,对应将A1的元素复写2次
B2 =
     1     1     2     2     2     3     3     3     3
% 输入的第二个参数是[2 3 4],对应将A1的元素复写2,3,4次
A3 =
     1     2
     3     4
B3 =
     1     1     1     2     2     2
     1     1     1     2     2     2
     3     3     3     4     4     4
     3     3     3     4     4     4
% 输入的第二个参数是2,输入的第三个参数是3
% 对应将A3的元素在列方向复写2次,行方向复写3次

索引

前面讲了那么多,终于可以讲最重要的索引部分。索引是什么?索引相当于编号,我们可以利用索引精确地找到我们想要的元素。无论是操作的输入还是输出,都要利用索引来实现。

A1 = [9 8 7 6 5 4 3 2 1]
B1_1 = A1(1) % 与很多程序语言不一样的是,MATLAB的索引从1开始,所以这一项返回第一个元素。
B1_2 = A1([1 3 5 2 1]) % 如果索引不止一个,以矩阵形式传入,可以一次性返回。
B1_3 = A1(1:2:7) % 冒号是使用索引的好助手
B1_4 = A1(2:6) % 冒号也可以这样使用
B1_5 = A1(:) % 只输入冒号相当于全部取出
B1_7 = A1(end) % 另一个强大的标记是end,表示该列(或者行)的最后一个索引
B1_8 = A1(3:end) % (如果矩阵的长度会变,这会避免不少麻烦)。

A2 = [4 5 6 7;5 7 9 0;  12 4 6 8; 0 -1 2  5]
B2_1 = A2(2,2) %二维矩阵可以用对应坐标取出
B2_2 = A2(2,:) %二维矩阵冒号相当于一行(或者一列)
B2_3 = A2(2:end,1:3) % 可以一次取出对应多行多列的元素组成新的矩阵。

% 特别的我们刚刚提到了一点:所有的矩阵在计算机中都是储存在线性空间里
% 那么下面这两个例子就是最好的演示
A3 = [1 2 3 4;5 6 7 8]
B3_1 = A3(5)
B3_2 = A3(5:7)
B3_3 = A3(:)
B3_4 = A3(:,:)

将以上命令输入至命令行,将得到以下输出:

A1 =
     9     8     7     6     5     4     3     2     1
B1_1 =
     9
% MATLAB的索引从1开始! MATLAB的索引从1开始! MATLAB的索引从1开始!
B1_2 =
     9     7     5     8     9
% 多个索引以矩阵形式输入即可,允许重复索引,顺序无关
B1_3 =
     9     7     5     3
B1_4 =
     8     7     6     5     4
% 冒号运算符可以线性关系的索引
B1_5 =
     9
     8
     7
     6
     5
     4
     3
     2
     1
% 只输入冒号运算符索引全部元素,但是这个时候变成了列向量(元素都是在内存中按列排放的)
B1_7 =
     1
% end是矩阵最后一个元素的索引
B1_8 =
     7     6     5     4     3     2     1
% end和冒号运算符的结合运用可以快捷取出元素
A2 =
     4     5     6     7
     5     7     9     0
    12     4     6     8
     0    -1     2     5
B2_1 =
     7
% 二维矩阵的元素可以用对应二维坐标取出
B2_2 =
     5     7     9     0
% 冒号作为矩阵行列索引,就是对应取出整行整列
B2_3 =
     5     7     9
    12     4     6
     0    -1     2
% 利用冒号运算符可以一次取出对应多行多列的元素组成新的矩阵。
A3 =
     1     2     3     4
     5     6     7     8
B3_1 =
     3
% 所有的矩阵在计算机中都是储存在线性空间里
% 实际上A3的线性排列 [1 5 2 6 3 7 4 8]
% 矩阵的第五个元素就是对应元素3
B3_2 =
     3     7     4
% 这种索引方式也可以用矩阵输入索引
B3_3 =
     1
     5
     2
     6
     3
     7
     4
     8
% 只输入冒号运算符索引全部元素,以列向量输出
B3_4 =
     1     2     3     4
     5     6     7     8
% A3(:,:)的形式可以取出整个二维矩阵,而不至于转成列向量

补充内容

本次的内容有点多,重点内容需要巩固:

  • size函数:目前来说最常见用于创建矩阵和确定循环结构的循环次数。
%% 1.模仿大师——创建一个一样大小的矩阵
a = [1 2 3 5;3 4  6 7];
b = zeros(size(a)); % 这就创建了一个大小完全一致的全零矩阵
% 试想如果a是外部输入的长度不确定的变量,这种方法就很高效
%% 2.循环次数
x = -1 : 0.1 : 3;
y = x;
for index = 1:size(x,2)
    y(index) = (x(index)-1) * (x(index)-2) + index;
end
plot(x,y,'r--','LineWidth',3); % 曲线绘图函数
  • reshape函数:重新排列矩阵,快速处理数据的手段
A = 1:15;
% 这样可以按列创建顺序的矩阵
B1 = reshape(A,3,5)
% 这样可以按行创建顺序的矩阵
B2 = reshape(A,5,3)'
% 三维数组为未尝不可
B3 = reshape(A,5,1,3)
  • sort函数:内置的sort函数比自己编写的排序更高效
x = [ 8 9 2 4 0 10 3 6 7 1];
y = x.*x;
plot(x,y,'r*-');
% 点还是那些点,但顺序不对会影响绘图质量
% 这时排序可以用上
[x1,index] = sort(x);
plot(x1,y(index),'r*-');
  • [ ]运算符:串联矩阵最重要的步骤
% 绘制斐波那契数列的曲线
x = 1:15;
y = [1,1];
for index = 3:size(x,2)
    y = [y y(end)+ y(end-1)];
end
plot(x,y,'ro-','LineWidth',3); % 曲线绘图函数
  • repmat函数:重复矩阵的拼接
% 字符串也可以拼接
a = ['hello']
b = repmat(a,3,2)
  • 索引:功能强大,针对性的选取数组元素
% 仍使用sort的案例
% 这里我并没有重新计算y1 = x*x,是因为索引能直接找到对应的y
x = [ 8 9 2 4 0 10 3 6 7 1];
y = x.*x;
plot(x,y,'r*-');
% 点还是那些点,但顺序不对会影响绘图质量
% 这时排序可以用上
[x1,index] = sort(x);
plot(x1,y(index),'r*-');

%% 索引的具体应用更重要的是逻辑变量和find函数(篇幅有限,之后补充)。

思考

每一行代码执行后,对应变量会有什么变化?

a = 2:3:8;
b = [a' a' a'];
c = b(1:2:3,1:2:3);
d = a + b(2,:);
w = [zero(1,3) ones(1,3)' 3:5'];
b([1,3],2) = b([3,1],2);
e = 1:-1:5;

解答:

a是一个1×3的矩阵 [    2   5   8   ]
b是一个3×3的矩阵 [    2   2   2;
                    5   5   5;
                    8   8   8   ]
c是一个2×2的矩阵[ 2   2;
                    8   8   ]
d是一个1×3的矩阵[ 7   10  13  ]
e是一个1×9的矩阵[ 0   0   0   1   1   1   3   4   5   ]
b([1    3],2)=[ 8   2   ]修改了原有b矩阵的值
实际上b发生改变 [  2   8   2;
                    5   5   5;
                    8   2   8   ]
(g)e是一个空矩阵

总结

本次的内容更多,已经划出重点,最大的重点是索引,结合逻辑矩阵能形成非常高效的作用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • 来源:NumPy Tutorial - TutorialsPoint 译者:飞龙 协议:CC BY-NC-SA 4...
    布客飞龙阅读 31,041评论 6 96
  • NumPy是Python中关于科学计算的一个类库,在这里简单介绍一下。 来源:https://docs.scipy...
    灰太狼_black阅读 1,202评论 0 4
  • 先决条件 在阅读这个教程之前,你多少需要知道点python。如果你想从新回忆下,请看看Python Tutoria...
    舒map阅读 2,539评论 1 13
  • 显示中文帮助的方法 预设→常规→帮助→在mathworks.com网站上(需要Internet连接)→语言(简体中...
    VeyronC阅读 2,367评论 0 34
  • 到今天为止,我们这个小班已有了八个学员,从六岁到六十岁,这太有趣了,六岁的小男生是李老师的儿子,和我们做同样的动作...
    微风空谷阅读 435评论 0 0