2016-06-09 2 views
2

Скажем, у меня есть следующая матрица:Расщепление группы в среде 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 ]'; 

я хотел бы разделить его на 4 группы, основываясь на знаках в первом столбце (т.е. все до знака флип одна группа):

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

и соответствующая группировка в секо й столбец будет затем:

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

Моя интуиция заключается в использовании

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

как первый шаг, но я не уверен, как продолжить оттуда. Любая помощь будет оценена, спасибо!

ответ

2

Чтобы создать этот массив ячеек, вы можете использовать accumarray. Сначала нам нужно присвоить уникальную ценность каждой «группе» последовательных номеров, которые имеют знак. Затем мы можем использовать accumarray, чтобы поместить все элементы в заданную группу в элемент массива ячеек.

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 

Если мы действительно хотим уменьшить его, так что одна линия мы могли бы сделать это.

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

Вот еще один способ:

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

Это использует mat2cell разделить A на куски и положить каждый в клетку. Длина фигур вычисляется с использованием sign для обнаружения знака, а затем diff и find для получения длины прогона.

1

Использование:

groupsSizes= diff([0;find(conv(A(:,1),[1,-1],'same')~=0)]); 
firstGroup = mat2cell(A(:,1),groupsSizes,1); 
secondGroup = mat2cell(A(:,2),groupsSizes,1); 
Смежные вопросы