web-dev-qa-db-fra.com

Comment supprimer zéro composant dans un vecteur dans Matlab?

J'ai un vecteur par exemple

a = [0 1 0 3]

Je veux transformer a en b qui est égal à b = [1 3].

Comment puis-je effectuer cela en général? J'ai donc un vecteur avec des composants nuls et je veux supprimer les zéros et ne laisser que les nombres non nuls?

37
xiaodai

Si vous souhaitez simplement supprimer les zéros, en laissant les non-zéros derrière dans un, alors la meilleure solution est

a(a==0) = [];

Cela supprime les éléments zéro, en utilisant une approche d'indexation logique dans MATLAB. Lorsque l'index d'un vecteur est un vecteur booléen de la même longueur que le vecteur, MATLAB peut utiliser ce résultat booléen pour l'indexer. C'est donc équivalent à

a(find(a==0)) = [];

Et, lorsque vous définissez certains éléments de tableau sur [] dans MATLAB, la convention consiste à les supprimer.

Si vous voulez mettre les zéros dans un nouveau résultat b, tout en laissant inchangé, la meilleure façon est probablement

b = a(a ~= 0);

Encore une fois, l'indexation logique est utilisée ici. Vous auriez pu utiliser la version équivalente (en termes de résultat) de

b = a(find(a ~= 0));

mais mlint finira par marquer la ligne comme celle où l'index purement logique était plus efficace, et donc plus approprié.

Comme toujours, méfiez-vous des tests EXACT pour zéro ou pour n'importe quel nombre, si vous auriez accepté des éléments d'un qui étaient dans une certaine tolérance epsilonique de zéro. Faites ces tests comme celui-ci

b = a(abs(a) >= tol);

Cela ne conserve que les éléments d'un qui sont au moins aussi grands que votre tolérance.

81
user85109

Je viens de rencontrer ce problème et je voulais trouver quelque chose sur la performance, mais je ne pouvais pas, alors j'ai écrit un script de benchmarking par moi-même:

% Config:
rows = 1e6;
runs = 50;

% Start:
orig = round(Rand(rows, 1));

t1 = 0;
for i = 1:runs
    A = orig;
    tic
    A(A == 0) = [];
    t1 = t1 + toc;
end
t1 = t1 / runs;

t2 = 0;
for i = 1:runs
    A = orig;
    tic
    A = A(A ~= 0);
    t2 = t2 + toc;
end
t2 = t2 / runs;

t1
t2
t1 / t2

Donc vous voyez, la solution utilisant A = A(A ~= 0) est la plus rapide des deux :)

8
tim

J'ai souvent fini par faire des choses comme ça. Par conséquent, j'ai essayé d'écrire une fonction simple qui "coupe" les éléments indésirables de manière simple. Cela met la logique matlab un peu à l'envers, mais semble bon:

b = snip(a,'0')

vous pouvez trouver le fichier de fonction à: http://www.mathworks.co.uk/matlabcentral/fileexchange/41941-snip-m-snip-elements-out-of-vectorsmatrices

Il fonctionne également avec tous les autres "x", nan ou autres éléments.

4
Nicolas

Les données

a=[0  3   0   0   7   10   3   0   1   0   7   7   1   7   4]

Faire

aa=nonzeros(a)'

Résultat

aa=[3   7   10   3   1   7   7   1   7   4]
3
MH A
b = a(find(a~=0))
3

Pourquoi pas simplement, a=a(~~a) ou a(~a)=[]. C'est équivalent aux autres approches mais certainement moins de touches.

2
Humberto77

Vous pouvez utiliser sparse (a), qui retournerait

(1,2) 1

(1,4) 3

Cela vous permet de conserver les informations sur l'emplacement de vos entrées non nulles.

2
python_enthusiast