2011-03-17 17 views
24

Powiel możliwe:
How can I divide each row of a matrix by a fixed row?Jak odjąć wektor z każdego rzędu macierzy?

szukam elegancki sposób, aby odjąć sam wektor z każdego wiersza macierzy. Oto nie elegancki sposób robienia tego.

a = [1 2 3]; 
b = rand(7,3); 
c(:,1) = b(:,1) - a(1); 
c(:,2) = b(:,2) - a(2); 
c(:,3) = b(:,3) - a(3); 

Również elegancki sposób nie może być wolniejszy od tej metody.

Próbowałem

c = b-repmat(a,size(b,1),1); 

i wydaje się wolniej.

EDIT: zwycięzcą jest ta metoda.

c(:,1) = b(:,1) - a(1); 
c(:,2) = b(:,2) - a(2); 
c(:,3) = b(:,3) - a(3); 

EDIT: więcej metod i tic toc Wyniki:

n = 1e6; 
m = 3; 
iter = 100; 
a = rand(1,m); 
b = rand(n,m); 

tic 
c = zeros(size(b)); 
for i = 1:iter 
    c(:,1) = b(:,1) - a(1); 
    c(:,2) = b(:,2) - a(2); 
    c(:,3) = b(:,3) - a(3); 
end 
toc 

tic 
c = zeros(size(b)); 
for i = 1:iter 
    c(:,1) = b(:,1) - a(1); 
    c(:,2) = b(:,2) - a(2); 
    c(:,3) = b(:,3) - a(3); 
end 
toc 

tic 
c = zeros(size(b)); 
for i = 1:iter 
    for j = 1:3 
     c(:,j) = b(:,j) - a(j); 
    end 
end 
toc 

tic 
for i = 1:iter 
    c = b-repmat(a,size(b,1),1); 
end 
toc 

tic 
for i = 1:iter 
    c = bsxfun(@minus,b,a); 
end 
toc 

tic 
c = zeros(size(b)); 
for i = 1:iter 
    for j = 1:size(b,1) 
     c(j,:) = b(j,:) - a; 
    end 
end 
toc 

wyniki

Elapsed time is 0.622730 seconds. 
Elapsed time is 0.627321 seconds. 
Elapsed time is 0.713384 seconds. 
Elapsed time is 2.621642 seconds. 
Elapsed time is 1.323490 seconds. 
Elapsed time is 17.269901 seconds. 
+2

To jest w zasadzie kopią tych innych pytań (sama idea, inna operacja arytmetyczna): [Jak mogę podzielić elementów macierzy przez sum kolumn w programie MATLAB?] (Http://stackoverflow.com/questions/1773099/how- do-i-divide-matrix-elements-by-column-sums-in-matlab), [Jak mogę podzielić każdy wiersz macierzy przez stały wiersz?] (http: // stackoverflow.com/questions/4723824/how-can-i-divide-each-row-of-a-matrix-by-a-fixed-row) – gnovice

+4

Dla tych zbyt leniwych, aby śledzić linki: 'c = bsxfun (@minus, b, a); ' – Jonas

+0

bsxfun wydaje się wolniejszy, patrz edycja – Miebster

Odpowiedz

1

Istnieją tylko trzy oczywiste odpowiedzi, a daliście dwa z nich w swoim pytaniu.

Trzeci jest przez rząd,

c(1,:) = b(1,:) - a; %... 

ale ja się spodziewać, że będzie wolniejszy niż przetwarzanie przez kolumnę o dużych matrycach ponieważ do elementów poza kolejnością pamięci.

Jeśli zmienisz przetwarzanie kolumn w pętlę for w pliku * .m lub podfunkcję, czy jest on nadal szybszy od wersji repmat?

Jedną rzeczą można przetestować szybkość Starają preallocating c.

c = zeros(size(b)); 
c(:,1) = b(:,1) - a(1); %... 
+0

Czwarty jest za pomocą 'bsxfun', jak wyjaśniono w duplikatach odpowiedzi, a także mój komentarz. – Jonas

6

Oto mój wkład:

c = b - ones(size(b))*diag(a)

teraz przyspieszyć testowanie go:

tic 
for i = 1:10000 
    c = zeros(size(b)); 
    b = rand(7,3); 
    c = b - ones(size(b))*diag(a); 
end 
toc 

Rezultat:

Elapsed time is 0.099979 seconds.

Nie tak szybko, ale jest czysto.

+0

Działa to również: 'b - ones (rozmiar (b, 1), rozmiar (a, 1)) * a' – suzanshakya

+0

Należy zauważyć, że jeśli rozmiar (b) jest bardzo duży, będzie to bardzo powolne i niezwykle nieefektywne w pamięci. repmat prawdopodobnie będzie działać lepiej w tym przypadku. –

Powiązane problemy