Изменить форму вертикальных блоков столбцов ниже предыдущих
В моем сценарии я генерирую матрицу, в которой каждый столбец связан по крайней мере с другим. Например, столбец 1 связан со столбцом 2, столбец 3 связан со столбцом 4 и т. Д. Но я также мог бы связать столбцы 3 на 3 или 4 на 4 или любое другое число.
На данный момент это всего лишь изображение, но затем я бы хотел переместить связанные столбцы на отдельной строке, чтобы я мог легко смешать их, используя any() или sum().
Это станет понятнее с этим примером:
A = reshape(1:12, 3, []) % A is the matrix I start with, this reshape is OK
A =
1 4 7 10
2 5 8 11
3 6 9 12
reshape(A, [], 2) % this reshape is not OK
ans =
1 7
2 8
3 9
4 10
5 11
6 12
Тем не менее, я хотел бы получить ответ:
ans =
1 4
2 5
3 6
7 10
8 11
9 12
Как я уже сказал, этот пример только для 2 столбцов, но в моем случае использования мне также нужно поддерживать любое количество пар столбцов. Здесь для 3 столбцов:
B = reshape(1:18, 3, [])
B =
1 4 7 10 13 16
2 5 8 11 14 17
3 6 9 12 15 18
reshape(B, [], 3)
ans =
1 7 13
2 8 14
3 9 15
4 10 16
5 11 17
6 12 18
Что бы я хотел:
ans =
1 4 7
2 5 8
3 6 9
10 13 16
11 14 17
12 15 18
Есть ли способ сделать это в векторизации?
2 ответа
Если предположить, M
чтобы быть входной матрицей, посмотрите, работает ли это для вас -
ncols = 2; %// number of columns (needs to be edited)
[m,n] = size(M) %// get size of input matrix for later usage
r = numel(M)/(m*ncols);
out = reshape(permute(reshape(M,m,ncols,[]),[1 3 2]),m*r,[])
Образцы прогонов -
M =
1 4 7 10
2 5 8 11
3 6 9 12
ncols =
2
out =
1 4
2 5
3 6
7 10
8 11
9 12
а также
M =
1 4 7 10 13 16
2 5 8 11 14 17
3 6 9 12 15 18
ncols =
3
out =
1 4 7
2 5 8
3 6 9
10 13 16
11 14 17
12 15 18
Охватывающий другой возможный заданный вопрос
Судя по твоим словам - "column 1 is coupled with column 2, column 3 is coupled with column 4, etc... But I could also couple columns 3 by 3 or 4 by 4 or any other number"
Я чувствую, что вы, возможно, действительно пытаетесь сформировать все возможные комбинации столбцов входной матрицы и вертикально объединить их, чтобы сформировать тонкую матрицу в качестве выходных данных. Этот раздел решения будет охватывать эту базу. Код для достижения такой цели (если это то, что вы имели в виду с надеждой) будет выглядеть примерно так:
ncols = 2; %// number of columns (needs to be edited)
[m,n] = size(M) %// get size of input matrix for later usage
combs = dec2base(0:n^2-1,n,ncols)-'0'+1 %// find combinations
combsp = permute(combs,[3 2 1]) %// make a 3D array of those combinations
idx = bsxfun(@plus,[1:m]',(combsp-1)*m) %//'# Indices as a 3D array
idx1 = reshape(permute(idx,[1 3 2]),m*size(idx,3),[]) %// vertically concatenate
%// 3D indices array into a 2D array
out = M(idx1) %// desired output
Один пробный прогон -
M =
6 7 3 6
3 1 6 3
5 1 4 2
ncols = 2
out =
6 6
3 3
5 5
6 7
3 1
5 1
6 3
3 6
5 4
6 6
3 3 ....
Решение Divakar является лучшим, но если вы, как и я, используете разреженные матрицы и Octave, Octave просто еще не поддерживает разреженные матрицы ND, поэтому вы не можете изменить форму, как это сделал Divakar:
Во-первых, хотя принципиально возможно иметь N-мерные разреженные объекты, разреженные классы Octave не позволяют их в настоящее время; Все экземпляры разреженных классов должны быть двумерными. Это означает, что SparseMatrix на самом деле больше похож на класс Matrix Octave, чем на класс NDArray.
Источник: документация GNU Octave
Единственный обходной путь - использовать решение на основе цикла, например, эту функцию:
function B = vertical_tile(A, ncols)
B = [];
if issparse(A)
B = sparse(B);
end
for i=1:ncols
B = [B A(:, i:ncols:end)];
end
B = reshape(B, [], ncols);
end
Результаты:
vertical_tile(A, 2)
ans =
1 4
2 5
3 6
7 10
8 11
9 12
vertical_tile(B, 3)
ans =
1 4 7
2 5 8
3 6 9
10 13 16
11 14 17
12 15 18