Попарные различия MATLAB в N-м измерении

Скажем, у меня есть N-мерная матрица A, которая может быть любого размера. Например:

A = rand([2,5,3]);

Я хочу вычислить все возможные попарные различия между элементами матрицы по заданному измерению. Например, если бы я хотел рассчитать различия по измерению 3, можно было бы создать такую ​​матрицу:

B = cat(3, A(:,:,2) - A(:,:,1), A(:,:,3) - A(:,:,1), A(:,:,3) - A(:,:,2));

Однако я хочу, чтобы это могло работать в любом измерении с матрицей любого размера. Итак, в идеале я хотел бы либо создать функцию, которая принимает матрицу A и вычисляет все попарные различия по измерению DIM, либо найти встроенную функцию MATLAB, которая делает то же самое.

Функция diff кажется полезной, но она только вычисляет различия между соседними элементами, а не все возможные различия.

Проводя исследование по этому вопросу, я нашел пара из сообщений о получении всех возможных различий, но большинство из них предназначены для элементов в векторе (и игнорируют проблему размерности). Кто-нибудь знает быстрое решение?


person Nolan Conaway    schedule 14.10.2015    source источник


Ответы (1)


Особые случаи измерения

Если вам не нужно общее решение, для случая dim=3 это будет так же просто, как пара строк кода -

dim = 3
idx = fliplr(nchoosek(1:size(A,dim),2))
B = A(:,:,idx(:,1)) - A(:,:,idx(:,2))

Вы можете перемещать эти idx(..) в определенные позиции измерения, если вы знаете размер заранее. Итак, скажем dim = 4, тогда просто делаем -

B = A(:,:,:,idx(:,1)) - A(:,:,:,idx(:,2))

Или допустим dim = 3, но A это массив 4D, тогда делаем -

B = A(:,:,idx(:,1),:) - A(:,:,idx(:,2),:)

Общий случай

Для дела Nth dim, кажется, вам нужно поприветствовать группу reshapes и permutes -

function out = pairwise_diff(A,dim)

%// New permuting dimensions
new_permute = [dim setdiff(1:ndims(A),dim)];

%// Permuted A and its 2D reshaped version
A_perm = permute(A,new_permute);
A_perm_2d = reshape(A_perm,size(A,dim),[]);

%// Get pairiwse indices for that dimension
N = size(A,dim);
[Y,X] = find(bsxfun(@gt,[1:N]',[1:N])); %//' OR fliplr(nchoosek(1:size(A,dim),2))

%// Get size of new permuted array that would have the length of 
%// first dimension equal to number of such pairwise combinations 
sz_A_perm = size(A_perm);
sz_A_perm(1) = numel(Y);

%// Get the paiwise differences; reshape to a multidimensiona array of same
%// number of dimensions as the input array
diff_mat = reshape(A_perm_2d(Y,:) - A_perm_2d(X,:),sz_A_perm);

%// Permute back to original dimension sequence as the final output
[~,return_permute] = sort(new_permute);
out = permute(diff_mat,return_permute);

return

Так много для обобщения, да!

person Divakar    schedule 14.10.2015
comment
Кажется, это работает, но не могу говорить о скорости/прозрачности. Огромное спасибо! - person Nolan Conaway; 15.10.2015