Изменить форму, чтобы вертикально расположить блоки столбцов ниже предыдущих

В моем скрипте я генерирую матрицу, в которой каждый столбец связан как минимум с другим. Например, столбец 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

Есть ли способ сделать это в векторной форме?


person gaborous    schedule 13.11.2014    source источник
comment
Это может помочь   -  person Luis Mendo    schedule 13.11.2014


Ответы (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 ....    
person Divakar    schedule 13.11.2014
comment
Отличный ответ, первый случай - это то, что мне нужно, но второй также будет очень полезен, это решает еще одну проблему, которую мне еще предстоит исправить. Однако этот ответ не работает в Octave с использованием разреженных матриц, потому что Octave еще не может обрабатывать разреженные матрицы в N-D, только в 2D... как в моем случае. Проклятый Октав. - person gaborous; 14.11.2014
comment
@ user1121352 Итак, разреженная вещь не будет работать ни в первом, ни во втором случае? Не думайте, что я мало что имел в виду, когда публиковал эти подходы, извините за это :) - person Divakar; 14.11.2014
comment
Я проверил с первым случаем, но я думаю, что это не сработает и со вторым случаем. Неважно, я не сказал о разреженности в вопросе, потому что я не знал об этом ограничении, которое характерно для Octave ... Я все равно не думаю, что есть хороший способ сделать вертикальную мозаику разреженных матриц в Octave , поэтому ваш ответ принят (либо нужно преобразовать в плотную матрицу, которая превосходит цель разреженности, либо использовать массив ячеек, но тогда он также не будет разреженным). - person gaborous; 14.11.2014
comment
Также это ограничение Octave является временным согласно документации, надеюсь, это будет исправлено в будущем. - person gaborous; 14.11.2014

Решение Divakar является лучшим, но если, как и я, вы используете разреженные матрицы и Octave, Octave просто еще не поддерживает разреженные матрицы N-D, поэтому вы не можете изменить форму, как это сделал 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
person gaborous    schedule 14.11.2014