2012-03-26 7 views
2

Ich habe eine Matrix:repeat Werte in einer Zeile 'N' Anzahl der Male, und dann die Werte inkrementieren - Matlab (variierend N)

mat = [ 2009 3 ; 
     2010 2 ] ; 

ich brauche die Sp1 gemäß Col2 zu wiederholen. Die Lösung unter Repeat copies of array elements: Run-length decoding in MATLAB ist hilfreich. Allerdings ist mein Hauptproblem, um dann die Jahre erhöht nach, wie in:

Ansmat = [ 2009 3 
      2010 3 
      2011 3 
      2010 2 
      2011 2 ] ; 

Ich möchte hier eine for Schleife zu vermeiden. Danke für Ihre Hilfe! Dies wäre eine große Hilfe!

Antwort

2

Sie können zunächst Ihre Matrix nachzubilden my vectorized answer to the previous question mit:

>> mat = [2009 3; 2010 2]; 
>> index = zeros(1, sum(mat(:, 2))); 
>> index([1; cumsum(mat(1:end-1, 2))+1]) = 1; 
>> Ansmat = mat(cumsum(index), :) 

Ansmat = 

     2009   3 
     2009   3 
     2009   3 
     2010   2 
     2010   2 

Als Nächstes können Sie einen Spaltenvektor von Offsets erstellen, um die Termine in der ersten Spalte hinzuzufügen. So können Sie dies auf vektorisierte Weise tun.

>> offset = ones(size(Ansmat, 1), 1); 
>> offset([1; cumsum(mat(1:end-1, 2))+1]) = [0; 1-mat(1:end-1, 2)]; 
>> Ansmat(:, 1) = Ansmat(:, 1)+cumsum(offset) 

Ansmat = 

     2009   3 
     2010   3 
     2011   3 
     2010   2 
     2011   2 
+1

Wow, das ist eine wahnsinnig clevere und schlaue Art, Kudos :) Eine kleine Korrektur; Das funktioniert also für eine Matrix mit mehr als zwei Zeilen, die Sie mat (1: end-1, 2) an den drei Stellen, an denen Sie es im [1 ...] Kontext verwenden, transponieren müssen. – GummiV

+0

@GummiV: Guter Fang. Ich habe einige Semikola hinzugefügt, um die Dimensionsabweichungen zu korrigieren, die bei größeren Matrizen auftreten würden. – gnovice

+0

@Gnovice danke. Ich hatte den von GummiV erwähnten Fehler bemerkt und ihn mit einem einfachen korrigiert; Danke..das ist wirklich schnell und schlau :) – Maddy

0

Ich bin nicht sicher, ob es eine Möglichkeit gibt, dies ohne eine Schleife zu tun, da dies eine etwas obskure Operation ist, die wir durchführen. Wenn ich Ihren Algorithmus verstehen sind hier richtig zwei Methoden, die eine einzelne for Schleife verwenden:

B = zeros(sum(A(:,2)), 2); 
counter = 1; 
for i = 1:size(A,2) 
    n = A(i,2); 
    B(counter:counter+n-1,1) = A(i,1)+(0:n-1)'; 
    B(counter:counter+n-1,2) = n; 
    counter = counter+n; 
end 

Sie könnten mit dem vorbelegen abschaffen. Wenn die counter Variable verwirrend ist, dann können Sie diese ausprobieren, die die Matrix B bei jeder Iteration anfügt, aber stattdessen einen Initialfall benötigt.

n = A(1,2); 
B = [A(1,1)+(0:n-1)', n*ones(n,1)]; 
for i = 2:size(A,2) 
    n = A(i,2); 
    B = [B; A(i,1)+(0:n-1)', n*ones(n,1)]; 
end 
0
incr = (0 : max(mat(:, 2)))'; 
incr = [incr, 0 * incr]; 
Ansmat = []; 
for k = 1 : size(mat, 1) 
    Ansmat = cat(1, Ansmat, repmat(mat(k, :), mat(k, 2), 1) + incr(1 : mat(k, 2), :)); 
end 

Aber wenn die erwartete Größe der Matrix Ansmat groß ist, wird die erste Lösung von GummiV schneller sein.

Verwandte Themen