MATLAB中的矩陣索引


利用矩陣的索引取出原矩陣的子集元素是一種有效的方式。MATLAB的多種索引不但類型強大、靈活,而且表達清晰易讀。在理解電腦MATLAB編程方面。體會MATLAB以矩陣為導向思想的高效性,掌握索引便是一種最佳方式。

索引也和MATLAB用戶經常聽到的另一個屬於“矢量/向量”緊密相關。矢量化意味着使用MATLAB的語法結構替代循環這一語法,能夠使程序運行得更快、更具有可讀性。當今大多數向量化的技術,許多都是借鑒了MATLAB的索引思想。在這篇文章中,將要學習其中的五種。

如果需要學習更多其他類似的方法,敬請參閱本文章結尾處的所列資源。

索引向量

讓我們以一個簡單向量為例,該向量僅有一個下標,向量:
v = [ 16 5 9 4 2 11 7 14];
下標可以是一個單一的值.
v (3) %取出第三個元素
ans =
9
或者下標本身可以是一個向量:
v( [1 5 6]) %取出第1、5、6個元素
ans =
16 2 11
MATLAB的冒號“:”提供了一個簡單方式取出向量v中連續范圍的元素
v (3 : 7) % 取出從第3到第7個的所有元素
ans =
9 4 2 11 7
向量V的兩個分區可以組成一個新的新的向量:
v([5:8 1:4])
ans =
1 至 7 列
2 11 7 14 16 5 9
8 列
4
特殊符號”end"快速取出向量v中最后一個元素:
v(end) % 取出最后一個元素
ans =
14
v(5:end) % 取出從第5個到最后一個元素
ans =
2 11 7 14
你甚至可以對符號”end“進行數學運算:
v(2:end-1) % 取出從第2個到向量倒數第2個的所有元素
ans =
5 9 4 2 11 7
將冒號":'和”end"組合起來可以產生巨大效果,例如取出一段范圍內以k為步進的向量元素集
v(1:2:end) % 取出奇數下標的元素
ans =
16 9 2 7
v(end:-1:1) % 逆序取出所有元素
ans =
1 至 7 列
14 7 11 2 4 9 5
8 列
16
通過在等式左邊使用索引表達式,你可以替換向量中特定元素:
v([2 3 4]) = [10 15 20]% 替代v中一些特定元素
v = 16 10 15 20 2 11 7 14
等式右邊的元素必須和等式左邊下標對應的元素保持一致。然而,你可以在等式右邊用標量
v([2 3]) = 30 % 第2和第3元素重新賦值為30
v =
1 至 7 列
16 30 30 4 2 11 7
8 列
14
這種索引賦值稱作 標量擴張

帶有兩個下標的索引矩陣

現在考慮矩陣索引的用法,我們用一個魔力方陣來做實驗:
A = magic(4)
A=
16 2 3 13

5 11  10  8

9 7   6  12

4 14  15  1

通常,矩陣索引用兩個下標 --一個作為行下標,一個作為列下標,最簡單方法取出矩陣一個元素如下:
A(2,4) % 取出第2行,第4列對應元素
ans =
8
更為常用的是,一個行下標或列下標可以是向量:
A(2:4,1:2)
ans =
5 11
9 7
4 14
在下標位置的一個符號":",是對”1:end“方便快捷的替代,總是用來選整行或整列元素:
A(3, :) % 取出完整的第3行
ans =
9 7 6 12
A(:,end) % 取出完整的最后一列
ans =
13
8
12
1
在這兒學習者總是迷惑:如何從矩陣中去取分散的幾個元素?例如,假定你想從矩陣A中取出坐標為(2,1),(3,2), 和 (4,4)的元素,表達式
A([2 3 4], [1 2 4])取出的顯然不是你所想要的,下面([2 4], [1 2 4])是如何工作的:
A([2 3 4], [1 2 4])
ans =
5 11 8
9 7 12
4 14 1

線性索引

表達式A(14)表示什么呢?
當你用帶一個下標的索引取出矩陣元素時,MATLAB默認矩陣中所有元素一個長列向量來存儲數據,如下:
16
5
9
...
8
12
1
因此,表達式A(14)取出列向量的第14個元素,用單一下標取出數據元素的方式稱作:線性索引
你可以知道A(14)和A(2,4)等價
單一下標可以是一個多個線性索引組合而成的向量,如下:
A([6 12 15])
ans =
11 15 12
再次考慮這個問題:從矩陣A中提取(2,1),(3,2), 和(4,4) 對應的元素?你可以通過用線性
索引來取出這些元素:
A([2 7 16])
ans =
5 7 1
從這個例子中你可以很簡單看出索引,但是長遠的你如何計算線性索引呢?MATLAB提供一個函數:sub2ind,該函數能夠將特定行列下標轉換為線性索引。你可以用這種方式提取特定元素:
idx = sub2ind(size(A), [2 3 4], [1 2 4])
ans =
2 7 16
A(idx)
ans =
5 7 1
關於用線性索引的最新例子:
例1:平移一個矩陣的數排
一個MATLAB用戶最近在comp.soft-sys.matlab新手組提出一個問題:
如果我想移動矩陣m-n列k次,我用A(:,[n-k+1:n1:n-k])實現,當如果k是一個數字集怎么辦?也就是說,倘若k是一個長度為m的向量呢,是否有快捷方便的辦法做到呢?

社區新手組貢獻者,Peter Acklam, 提出了用”sub2ind“和線性索引來解決:

%這個例子我沒看,以后有工夫再研究
% index vectors for rows andcolumns
p = 1:m;
q = 1:n;
% index matrices for rows andcolumns
[P, Q] = ndgrid(p, q);
% create a matrix with the shiftvalues
K = repmat(k(:), [1 n]);
% update the matrix with the columnindexes
Q = 1 + mod(Q+K-1, n);
% create matrix of linear indexes
ind = sub2ind([m n], P, Q);
% finally, create the output matrix
B = A(ind);

例2:使矩陣的一些元素為0

另一個MATLAB用戶提出這個問題。
我想獲取每一個的最大值,這不是什么大問題,但是之后我想令其他元素為0,比如,矩陣:
1 2 3 4

5 5 6 5

7 9 8 3

should become:

0 0 0 4

0 0 6 0

0 9 0 0

另一個社區貢獻者,BrettShoelson,提出了解決辦法:

%這里用到的函數很簡單,搜一下就知道用法啦
[Y,I]= max(A, [], 2);%獲取每一行最大值,結果 存在列向量Y中,I里存的是每行最大值的列位置。

B = zeros(size(A));%建立一個和A同等大小的矩陣

B(sub2ind(size(A), 1:length(I),I')) = Y;%將三個最大值分別放到線性索引對應的位置上

邏輯索引

另一個索引變量,邏輯索引,已被證明其有用並且易於表達。在邏輯索引中,你可以為矩陣下標使用一個單一的邏輯數組,MATLAB取出邏輯判斷為真的元素,輸出經常是一個列向量。例如,A(A>2)取出矩陣A中所有大於12的元素
A(A > 12)
ans =
16
14
15
13
許多MATLAB函數以“is"開頭,返回邏輯數組,這對於邏輯索引非常有用。

例如,你可以用另外一個值來替代一個數組中所有不是數字的數:NaNs,這里使用函數isnan,邏輯索引和標量擴張。矩陣B中所有NaN元素都賦值為0
B(isnan(B)) = 0

或者亦可以將字符串矩陣中所用空格用下划線‘_'代替

str(isspace(str)) = '_'
邏輯索引和函數find關系緊密。表達式A(A>5)等價於A(find(A>5))。你所用哪種主要取決於你的風格和代碼可讀性

但是這種取舍也取決於是否你需要實際的索引去做一些其他的計算。

例如,假定你想暫時將矩陣中NaN(不為數字的元素)賦值為0,做一些運算。之后將NaN(不為數字的元素)重新放回矩陣原位置。在這個例子中,2維濾除使用函數:filter2,你可能會這樣做:

nan_locations = find(isnan(A));
A(nan_locations) = 0;
A = filter2(ones(3,3), A);
A(nan_locations) = NaN;

我們希望在這一篇文章中列舉的MATLAB索引變量能夠給你一個感覺,你可以高效精簡的描述算法。在你的MATLAB編程中,使用這些技術和與之相關的函數能夠增強你創造出熟練地、易讀地和矢量化的代碼的能力.

參考文獻

王茂春於2015年12月27日 東六實驗室
MATLAB中的矩陣索引


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM