2010-05-28 6 views
1

J'ai une matrice de dimension variable, X. Je veux une fonction qui obtiendra la première moitié de X dans une dimension. I.E., je veux quelque chose comme ceci:MATLAB submatrix sur les dimensions variables

function x = variableSubmatrix(x, d) 
    if d == 1 
     switch ndims(x) 
      case 1 
       x = x(1:end/2); 
      case 2 
       x = x(1:end/2, :); 
      case 3 
       x = x(1:end/2, :, :); 
      (...) 
     end 
    elseif d == 2 
     switch ndims(x) 
      case 2 
       x = x(:, 1:end/2); 
      case 3 
       x = x(:, 1:end/2, :); 
      (...) 
     end 
    elseif (...) 
    end 
end 

Je ne suis pas tout à fait sûr comment faire cela. J'ai besoin d'être rapide, car cela sera utilisé plusieurs fois dans le calcul.

Répondre

7

Cela devrait faire l'affaire:

function x = variableSubmatrix(x, d) 
    index = repmat({':'},1,ndims(x)); %# Create a 1-by-ndims(x) cell array 
            %# containing ':' in each cell 
    index{d} = 1:size(x,d)/2;   %# Create an index for dimension d 
    x = x(index{:});     %# Index with a comma separated list 
end 

Ce qui précède crée d'abord un réseau de cellules 1-sous-ndims(x) avec ':' dans chaque cellule. La cellule correspondant à la cote d est alors remplacée par un vecteur contenant les nombres 1 à la moitié de la taille de la cote d. Ensuite, le contenu du tableau de cellules est généré en tant que comma-separated list (en utilisant la syntaxe {:}) et utilisé comme index dans x. Cela fonctionne parce que ':' et : sont traités de la même manière (c'est-à-dire "tous les éléments de cette dimension") lorsqu'ils sont utilisés dans une instruction d'indexation.

+0

Wow, ce qui est grand! Je ne connaissais pas '': ''non plus! – rlbond

0

Vous pouvez utiliser s = size(X) pour obtenir les dimensions X, puis essayez X(1:floor(s(1)),:) pour obtenir la moitié de la matrice.

Notez que size renvoie un tableau vectoriel contenant la longueur dans chaque dimension (par exemple, une matrice 2x3 retournera une taille de [2 3]). En tant que tel, vous voudrez peut-être changer s(1) à n'importe quelle dimension vous avez besoin.

Exemple:

a = [1 2 3 4; 5 6 7 8;] 

s = size(a);   % s = [2 4] 

b = a(1:s(1)/2,:); % b = [1 2 3 4]; 
c = a(:,1:s(2)/2); % c = [1 2; 5 6]; 
0

Pour ce que ça vaut la peine, voici la solution en Python (avec numpy):

à réduire de moitié la dimension i:

def halve(x,i): 
    return x[(slice(None),)*i+(slice(x.shape[i]/2),)] 

x = zeros([2,4,6,8]) 
y = halve(x,2) # dimension 2 was 6 
y.shape # (2,4,3,8) # dimension 2 is now 3 

Si vous voulez juste réduire de moitié la première dimension, puis x[:len(x)/2] est suffisante .

Modifier

J'ai eu quelques commentaires sceptiques, sur ma précédente solution, x[:len(x)/2], alors voici un exemple:

x=zeros([4,2,5,6,2,3]) # first dimension is 4 
len(x) # 4 
x.shape # 4,2,5,6,2,3 
x[:len(x)/2].shape # 2,2,5,6,2,3 <- first dimension divided by two 
+0

Est-ce que ça va vraiment marcher? L'OP veut diviser la matrice par deux * suivant une dimension spécifique *. Le mot-clé 'end' ne représente pas le nombre total d'éléments de la matrice, il représente la longueur maximale de la dimension qu'il indexe. – gnovice

+0

-1, ce que gnovice a dit. – mtrw

+0

J'insiste sur le fait que cela fonctionne. Cela fonctionne parce que 'len (x)' est la longueur du tenseur sur la première dimension, ce n'est pas * le nombre total d'éléments. –

Questions connexes