2016-08-16 4 views
0

In MatLab habe ich zwei Matrizen (Matrizen können in der Größe variieren). Ich möchte Spalten von B greifen und ihnen jeden n-ten Spalte in A.Matlab: Interleave Proben nach Spalte

Hier ist ein kleines Beispiel einfügen:

Fall I

Annahmen für diesen Fall:

Spalten sind ein Vielfaches von 2 und Zeilen sind die gleichen für A und B

A =

1 2 3 4 
5 6 7 8 

B =

1 2 
3 4 

Ich möchte diese

bekommen

c =

1 2 1 3 4 2 
5 6 3 7 8 4 

Der Code auch für einen anderen Fall wie funktionieren sollte:

Fall II

Annahmen für diesen Fall:

Spalten sind ein Vielfaches von 3 und die Zeilen sind die gleichen für A und B

A =

123456789 
123456789 

B =

123456 
123456 

C =

12312 45634 78956 
12312 45634 78956 

Ich weiß, MatLab hat eine Umform- und Permutierfunktion, aber ich konnte nicht die richtigen Ergebnisse erzielen. Ich weiß, dass ich eine for-Schleife verwenden könnte, oder manuelles concat durch Indizierung, aber dachte, dass die Verwendung dieser Funktionen eine bessere Leistung haben würde. Jede hep wäre großartig.

+0

Gibt es ein bestimmtes Muster für die Umformung? – zhqiat

+0

Ich möchte Spalten von B greifen und sie jede n-te Spalte in A einfügen. – wwjdm

+0

Sind wir garantiert immer genug Werte, um das neue Array (und nicht mehr) zu füllen? Was wäre, wenn "B" im zweiten Beispiel nur 3 Spalten hätte? Wie würde das Ergebnis aussehen? Was wäre, wenn "B" 12 Spalten hätte? – beaker

Antwort

1

Ich glaube, ich das Rätsel gelöst:

  • I A und B Matrizen Vektoren umgewandelt, weil es einfacher ist, Vektor-Indizierung als Matrix Indizierung zu verwenden.
  • Ich bereitete einen Vektor der korrekten Indizes der A- und B-Elemente unter Verwendung der Index-Modulo-Dimension vor.

Überprüfen Sie die folgende Lösung:

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

B =[1 2 
    3 4]; 

aN = size(A, 2); 
bN = size(B, 2); 

cM = size(A,1); 
cN = aN + bN; 

a = A(:); 
b = B(:); 

%Initialize vector C with zeros. 
c = zeros(length(a) + length(b), 1); 

a_indeces = 1:length(c); 
b_indeces = 1:length(c); 

%Create array of indeces matches rquiered position of A elements. 
a_indeces = a_indeces(mod(a_indeces-1, cN) < aN); %[1:4, 7:10] 

%Create array of indeces matches rquiered position of B elements (add aN because B elements follows A elements). 
b_indeces = b_indeces(mod(b_indeces-1, cN) < bN) + aN; %[5:6, 11:12] 

%Fill c elements as vector. 
c(a_indeces) = a; 
c(b_indeces) = b; 

%Reshape c to matrix. 
C = reshape(c, [cM, cN]); 

ich eleganteren Weg gefunden, das besser funktioniert:

A = [ 1 2 3 4 
     5 6 7 8 
     9 10 11 12]; 

B =[11 12 
    13 14 
    15 16]; 

aN = size(A, 2); 
bN = size(B, 2); 
cN = aN + bN; 

a_indeces = 1:cN; 
b_indeces = 1:cN; 

%Create array of column indeces matches A elements. 
a_indeces = a_indeces(mod(a_indeces-1, floor(cN/bN)) < floor(aN/bN)); 

%Create array of column indeces matches B elements. 
b_indeces = b_indeces(mod(b_indeces-1, floor(cN/bN)) >= floor(aN/bN)); 

C = zeros(size(A,1), cN); 

C(:, a_indeces) = A; 
C(:, b_indeces) = B; 
1

Angenommen A ist immer genau n-mal so breit wie B, Sie können den folgenden Code verwenden, um c:

A = [ 1 2 3 4 5 6; 7 8 9 10 11 12 ] 
B = [ 13 14; 15 16 ] 

NA = size(A, 2); 
NB = size(B, 2); 
n = NA/NB; 

# Make a combined array 
AB = [A B] 

# Pick columns from A and B part in AB, respectively 
colsA = reshape(1:NA, [n, NB]) 
colsB = reshape(1:NB, [1, NB]) + NA 

cols = [colsA; colsB] 


c = AB(:, cols(:)) 
zu generieren

Die Grundidee besteht darin, zuerst A und B horizontal als AB zu verketten. Dann würde c gleich AB(:, [1:n, NA+1, (1:n)+n, NA+2, (1:n)+2*n, NA+3 ... ]) sein. Das Spaltenindexarray wird durch Interleaving und [NA+1, NA+2, NA+3 ... ] erzeugt; beide können bequem unter Verwendung einer Umformung wie oben konstruiert werden.

+0

Danke, aber die Matrix ist nicht immer n mal so breit. – wwjdm

+0

Ich verstehe. Es wäre jedoch besser, wenn Sie ein wenig genauer über _exactly_ wie flexibel Sie die Lösung sein möchten. Andernfalls sind die Antworter gezwungen, (oft falsche) Annahmen zu treffen. –

+0

Ihr richtig, also habe ich einen anderen Fall hinzugefügt und meine Frage aktualisiert. – wwjdm

3

Sie müssen zuerst A so umgestalten, dass es so breit wie B ist, verketten Sie B vertikal und formen Sie es dann auf die ursprüngliche Höhe um.

>> C = reshape([reshape(A, [], size(B,2)); B], size(B,1), []) 
C = 

    1 2 1 3 4 2 
    5 6 3 7 8 4 

* Angenommen size(A, 1) == size(B, 1), natürlich.

function C = groupcols(A, B) 
% interleave columns of A and B such that 
% for m = number of columns of A, and n = number of columns of B 
% the output matrix C has alternating groups of 
%  m/gcd(m,n) columns of A, followed by 
%  n/gcd(m,n) columns of B 
% if gcd(m,n) == 1, then C will be all columns of A followed by 
%  all columns of B 

m = size(A,2); 
n = size(B,2); 
g = gcd(m,n); 

C = [reshape(A, size(A,1)*m/g, []); reshape(B, size(B,1)*n/g, [])]; 
C = reshape(C, size(A,1), []); 

Mit der Eingabe:

A = 

    1 2 3 4 5 6 7 8 9 
    1 2 3 4 5 6 7 8 9 

B = 

    11 12 13 14 15 16 
    11 12 13 14 15 16 

Die


Um dies zu verallgemeinern, können wir die Anzahl der Gruppen jeder Anordnung durch Auffinden der ggT der Zahlen von Spalten finden Ausgabe ist:

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

Da der größte gemeinsame Teiler von 9 Spalten und 6 Spalten 3 ist, gibt es 3 Gruppen mit 3 Spalten von A und 2 Spalten von B.

+0

Das ist großartig, aber was, wenn Sie ändern möchten, wo Sie die Spalten einfügen. – wwjdm

+0

In welcher Weise ändern? Dies räumt die eingefügten Spalten gleichmäßig auf, so dass 'size (A, 2)' gleichmäßig durch 'size (B, 2)' teilbar sein muss.Wenn Sie zum Beispiel 6 Spalten in "A" und 2 Spalten in "B" hätten, würde dies Ihnen drei Spalten von "A", eine Spalte von "B", drei Spalten von "A", eine Spalte von 'geben B'. Wenn Sie unterschiedliche Abstände wünschen, dann brauche ich wahrscheinlich ein Beispiel. – beaker

+0

Ihr richtig, also habe ich einen anderen Fall hinzugefügt und meine Frage aktualisiert. – wwjdm