2016-11-09 4 views
4

У меня есть матрица 2D, где № столбцов всегда кратны 3 (например 250×27) - из-за повторяющуюся организацию результатов (A,B,C, A,B,C, A,B,C, и так далее). Я хочу изменить эту матрицу, чтобы создать новую матрицу с тремя столбцами - каждая из которых содержит агрегированные данные для каждого типа (A,B,C) (например, 2250×3).Сворачивания матрицы на столбцы

Таким образом, в матрице 250×27 все данные в столбцах 1,4,7,10,13,16,19,22,25 будут объединены, чтобы сформировать первый столбец результирующей матрицы с преобразованием.

Второй столбец в полученной реконструированной матрице будет содержать все данные из столбцов 2,5,8,11,14,17,20,23,26 - и так далее.

Есть ли простой способ сделать это в MATLAB? Я только знаю, как использовать reshape, если столбцы, которые я хотел объединить соседствовали (1,2,3,4,5,6), а не несмежных (1,4,7,10,13,16) и т.д.

ответ

3

Shameless украсть @Divakar:

B = reshape(permute(reshape(A,size(A,1),3,[]), [1,3,2]), [], 3); 
1

Пусть A быть ваша матрица. Вы можете сохранить каждый третий столбец в одной матрице, например: (обратите внимание, что вам не нужно сохранять их в виде матриц отдельно, но это упрощает чтение этого примера).

A = rand(27); %as test 
B = A(:,1:3:end); 
C = A(:,2:3:end); 
D = A(:,3:3:end); 

Затем вы используете Reshape:

B = reshape(B,[],1); 
C = reshape(C,[],1); 
D = reshape(D,[],1); 

И, наконец, все это вместе:

A = [B C D]; 
+0

Я полагаю, что это можно сделать более компактным, пропуская средний блок и использование 'B (:)' в последнем блоке, но в целом это похоже на правильный путь. –

2

Вы можете рассматривать каждый набор столбцов как один элемент и сделать три перекраивает вместе , Это должно сделать трюк:

[Сохранить как файл «reshape3.m» в вашей папке Matlab назвать ее как функцию]

function out = reshape3(in) 
    [~,C]=size(in); % determine number of columns 
    if mod(C,3) ~=0 
     error('ERROR: Number of rows must be a multiple of 3') 
    end 

    R_out=numel(in)/3; % number of rows in output 

    % Reshape columns 1,4,7 together as new column 1, column 2,5,8 as new col 2 and so on 
    out=[reshape(in(:,1:3:end),R_out,1), ... 
     reshape(in(:,2:3:end),R_out,1), ... 
     reshape(in(:,3:3:end),R_out,1)]; 
end 
-2

Попробуйте Matlab function mat2cell, я думаю, что эта форма допускается.

X is the "start matrix"  
C = mat2cell(X, [n], [3, 3, 3]); %n is the number of rows, repeat "3" as many times as you nedd 

%extract every matrix 
C1 = C{1,1}; %first group of 3 columns 
C2 = C{1,2}; %second group of 3 columns 
%repeat for all your groups 

%join the matrix with vertcat 
Cnew = vertcat(C1,C2,C3); %join as many matrix n-by-3 as you have 
+2

Не будет работать (наиболее очевидным намеком является то, что C1 == C2), также, как правило, плохой идеей использовать ячейки для перехода от 1 матрицы к другой, поскольку это довольно неэффективно. –

+0

@DennisJaheruddin C1 = C2 - это, очевидно, моя ошибка в индексе обжатия (обновлена), и спасибо. Почему встроенная функция Matlab считается довольно неэффективной? – marcoresk

+0

встроенные функции в целом в порядке. Но ячейка - гораздо более универсальный тип данных, чем матрица. Поэтому не должно быть неожиданностью, что обычно лучше работать с матрицей, а не преобразовывать ее в ячейку, работать в ячейке и преобразовывать ее в матрицу. - Для небольших проблем эффективность не может быть проблемой, но в этом случае я бы все же утверждал, что это лучшая практика для ясности кода, придерживаться матриц, если нет веской причины не делать этого. –

1

Позволяет предположим, что матрица 3х6 A

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

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

вы извлечь размер матрицы

b =size(A) 

, а затем извлечь каждый третий столбец для одной строки

c1 = A((1:b(1)),[1:3:b(2)]) 
c2 = A((1:b(1)),[2:3:b(2)]) 
c3 = A((1:b(1)),[3:3:b(2)]) 

и поместить их в одну матрицу

A_result = [c1(:) c2(:) c3(:)] 

A_result = 

    1  2  3 
    6  5  4 
    2  3  4 
    4  5  6 
    3  2  1 
    5  6  7 
+1

Хотя он работает, он, похоже, не добавляет существенных ответов и комментариев. –

+0

@DennisJaheruddin Не было ответов, когда я увидел этот вопрос, поэтому просто поделился другим способом сделать это – Umar

0

Вот мой 2 минуты взять на него:

rv = @(x) x(:); 
ind = 1:3:size(A,2); 
B = [rv(A(:,ind)) rv(A(:,ind+1)) rv(A(:,ind+2))]; 

спасает несколько некрасивых reshape с, может быть немного медленнее, хотя.

1

Мои 2 цента:

nRows = size(matrix, 1); 
nBlocks = size(matrix, 2)/3; 
matrix = reshape(matrix, [nRows 3 nBlocks]); 
matrix = permute(matrix, [1 3 2]); 
matrix = reshape(matrix, [nRows * nBlocks 1 3]); 
matrix = reshape(matrix(:), [nRows * nBlocks 3]); 
0

Если у вас есть Image Processing Toolbox, im2col является очень удобным решением:

out = im2col(A,[1 4], 'distinct').' 
Смежные вопросы