2012-09-06 17 views
2

我具有矩陣說更改矩陣的多個元素(的已知座標),而不for循環

Z = [1 2 3; 
    4 5 6; 
    7 8 9] 

我必須改變其值,在位置(2,2)和說(3,1 ),某些指定的值。我有兩個矩陣rowNoscolNos含有這些位置:

rowNos = [2, 3] 
colNos = [2, 1] 

比方說,我想在這些位置來改變元素的值設置爲0

我怎麼能做到這一點,而不使用循環?

+0

爲什麼你想避免在這裏的循環? –

+2

@MarcusRiemer,因爲我打算在大型圖像上應用這個東西。事實上是巨大的。我感覺,Vectorization將幫助我的代碼比普通的循環更快地運行。 – shahensha

回答

5

使用sub2ind,它會你的分項指數轉換爲線性指標,這是一個數字指向矩陣中的一個確切點(more info)。

Z = [ 1 2 3 ; 4 5 6 ; 7 8 9]; 
rowNos = [2, 3]; 
colNos = [2, 1]; 

lin_idcs = sub2ind(size(Z), rowNos, colNos) 

如果你想在一個特定的行和列(在更高維度即元素)的所有元素進行操作,也可以使用線性索引解決這些問題。它才成爲計算它們的一些技巧:

Z = reshape(1:4*4*3,[4 4 3]); 
rowNos = [2, 3]; 
colNos = [2, 1]; 

siz = size(Z); 
lin_idcs = sub2ind(siz, rowNos, colNos,ones(size(rowNos))); % just the first element of the remaining dimensions 
lin_idcs_all = bsxfun(@plus,lin_idcs',prod(siz(1:2))*(0:prod(siz(3:end))-1)); % all of them 
lin_idcs_all = lin_idcs_all(:); 

Z(lin_idcs_all) = 0; 

實驗了一下與sub2ind,並通過我的代碼一步一步的去了解它。

它會一直更容易,如果這是你想要採取的所有元素關閉第一個維度,那麼你也可以使用冒號運算:

Z = reshape(1:3*4*4,[3 4 4]); 
rowNos = [2, 3]; 
colNos = [2, 1]; 

siz = size(Z); 
lin_idcs = sub2ind(siz(2:end),rowNos,colNos); 
Z(:,lin_idcs) = 0; 
+0

非常感謝@Gunther Struyf。還有一個小問題。我如何將它擴展到三維矩陣?如果Z被稱爲3x3x3矩陣,該怎麼辦? (我實際上想要改變圖像的RGB值,所以我已經用這種方式簡化了它)所以,如何將3個值與每個位置相關聯,並且我想用3個其他指定值來更改它們。我怎麼做? – shahensha

+0

@Shahensha請參閱編輯^^(你應該在你的原始問題中在第一個地方添加註釋) –

+0

非常感謝@Gunter Struyf – shahensha

2

使用sub2ind具有多個條目的行和列

Z(sub2ind(size(Z), rowNos, colNos))=0 

Z = [1 2 3; 
    4 5 6; 
    7 8 9]; 

rowNos = [2, 3]; 
colNos = [2, 1]; 

Z(sub2ind(size(Z), rowNos, colNos))=0 

Z = 

    1  2  3 
    4  0  6 
    0  8  9 
+0

非常感謝@gevang。 還有一個小問題。我如何將它擴展到三維矩陣?如果Z被稱爲3x3x3矩陣,該怎麼辦? (我實際上想要改變圖像的RGB值,所以我已經這樣簡化了它) 那麼如何有3個值與每個位置相關聯,我想用3個其他指定值來改變它們。我怎麼做? – shahensha

+0

沿着與@Gunther Struyf相同的線條,我也建議用於在第三維上循環的3維矩陣(即RGB-圖像),其是乾淨的並且不費錢(即使對於巨大的二維維度),即'c = [ - 1; -2; -3];對於i = 1:3,Z(sub2ind(size(Z),rowNos,colNos,repmat(i,1,size(rowNos,2))))= c(i)結束' – gevang

1

你想做到這一點

z(rowNos, colNos) 

但你不能 - MATLAB做了指數的笛卡爾乘積。您可以這樣做:

idx=(colNos-1)*size(z, 1)+rowNos; 
z(idx)=0 

展平z矩陣並通過線性索引訪問它,該索引是rowNos和colNos的組合。請記住,MATLAB通過列平坦化矩陣(基於列的矩陣存儲)。

+1

這實際上是'sub2ind'的作用,但是這隻適用於2d矩陣當然這裏有訣竅,但對於連續性來說,使用sub2ind更容易) –

+0

對於更高維度,您可以執行相同的技巧,這不是真正的技巧,而是sub2ind的功能。但其確實需要知道MATLAB數據結構。 sub2ind將你從中解脫出來,但我很想知道事情是如何運作的。 – angainor

+0

(nofi),所以你也可以使用'sum(x)/ length(x)'來計算矢量的均值:p –