2016-06-09 8 views
2

Sagen wir, ich habe folgende Matrix:Splitting Gruppen in MATLAB

A(:,1) = [-5 -5 5 5 -5 -5 -5 -5 5 5 5 5]'; 
A(:,2) = [8 7 3 6 5 9 8 7 9 4 3 2 ]'; 

Ich möchte es in 4 Gruppen basierend aufgeteilt auf die Zeichen in der ersten Spalte (dh alles, was vor ein Zeichen Flip ist eine Gruppe):

1) -5 -5
2) 5 5
3) -5 -5 -5 -5
4) 5 5 5 5

und der entsprechenden in der seco Gruppierungs nd Spalte wäre dann:

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

Meine Intuition verwenden

diff(A(:,1)) ~= 0 

als der erste Schritt, aber ich bin mir nicht sicher, wie man von dort weitergeht. Jede Hilfe wäre willkommen, danke!

Antwort

2

Sie können accumarray verwenden, um dieses Zellen-Array für Sie zu erstellen. Wir müssen zuerst jeder Gruppe von aufeinanderfolgenden Nummern, die sich ein Zeichen teilen, einen eindeutigen Wert zuweisen. Wir können dann accumarray verwenden, um alle Elemente in einer bestimmten Gruppe in ein Element eines Zellenarrays zu platzieren.

A = cat(1, [-5 -5 5 5 -5 -5 -5 -5 5 5 5 5], [8 7 3 6 5 9 8 7 9 4 3 2 ]).'; 

% Compute the sign of each element: -1 for negative, 1 for positive 
% Repeat first element for diff 
S = sign(A([1 1:end],1)); 
% -1 -1 -1  1  1 -1 -1 -1 -1  1  1  1  1 

% Compute element-by-element differences 
D = diff(S); 
% 0  0  2  0  -2  0  0  0  2  0  0  0 

% Convert to a logical matrix which will make any non-zero 1 and any zero stays 0 
L = logical(D); 
% 0  0  1  0  1  0  0  0  1  0  0  0 

% Take the cumulative sum (and add 1) to give each group of elements a unique number 
subs = cumsum(L) + 1; 
% 1  1  2  2  3  3  3  3  4  4  4  4 

% Use this as the first input to accumarray and perform a given action on all elements in 
% A(:,2) which share these values. Our action will be to convert to a cell array 
result = accumarray(subs, A(:,2), [], @(x){x}); 

% result{1} = 
%  8  7 
% 
% result{2} = 
%  3  6 
% 
% result{3} = 
%  5  9  8  7 
% 
% result{4} = 
%  9  4  3  2 

Wenn wir es wirklich so eine einzelne Linie reduzieren möchten, könnten wir dies tun.

accumarray(1 + cumsum(logical(diff(sign(A([1 1:end],1))))), A(:,2), [], @(x){x}) 
1

Hier ist eine andere Art und Weise:

result = mat2cell(A(:), diff([0; find([diff(sign(A(:))); true])])); 

Diese mat2cell verwendet A in Stücke aufgeteilt und jeweils in eine Zelle gesteckt. Die Länge der Teile wird unter Verwendung von sign berechnet, um das Vorzeichen zu erkennen, und dann diff und find, um die Lauflängen zu erhalten.

1

Verwendung:

groupsSizes= diff([0;find(conv(A(:,1),[1,-1],'same')~=0)]); 
firstGroup = mat2cell(A(:,1),groupsSizes,1); 
secondGroup = mat2cell(A(:,2),groupsSizes,1);