2010-04-14 26 views
36

que tienen un vector, por ejemplo,Cómo eliminar componentes cero en un vector en Matlab?

a = [0 1 0 3] 

Quiero convertir a en b que es igual a b = [1 3].

¿Cómo realizo esto en general? Entonces, ¿tengo un vector con algunos componentes cero y quiero eliminar los ceros y dejar solo los números que no sean cero?

Respuesta

79

Si sólo desea eliminar los ceros, dejando a los no-ceros detrás de una, entonces la mejor solución es

a(a==0) = []; 

Esto elimina los elementos cero, usando un enfoque de indexación lógica en MATLAB. Cuando el índice de un vector es un vector booleano de la misma longitud que el vector, MATLAB puede usar ese resultado booleano para indexarlo. Así que esto es equivalente a

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

Y, al configurar algunos elementos de la matriz a [] en MATLAB, la convención es para eliminarlos.

Si usted quiere poner los ceros en un nuevo resultado b, dejando un sin cambios, la mejor manera es probablemente

b = a(a ~= 0); 

Una vez más, la indexación lógica se utiliza aquí. Se podría haber utilizado la versión equivalente (en términos de resultado) de

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

pero mlint el resultado final será marcar la línea como uno en el que el índice puramente lógico era más eficiente, y por lo tanto más apropiado.

Como siempre, tenga en cuenta EXACT pruebas para cero o para cualquier número, si hubiera aceptado elementos de a que estuvieran dentro de una tolerancia épsilonica de cero. Haga esas pruebas como

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

Esto conserva solo aquellos elementos que son al menos tan grandes como su tolerancia.

+1

o para el primer ejemplo, 'a = a (a ~ = 0)' es suficiente, la asignación en contexto funciona bien. Buen punto para probar contra un número pequeño en lugar de 0. – mtrw

+0

@woodchips: Acabo de publicar una comparativa de rendimiento a continuación :) – tim

3
b = a(find(a~=0)) 
+2

simplemente 'b = a (find (a))' es suficiente, el valor predeterminado es buscar valores distintos de cero. – wich

+5

o 'b = a (a ~ = 0)' es suficiente, la indexación lógica está implícita. – mtrw

+1

Buenos comentarios, me siento mal por haber votado mi pobre respuesta. –

8

me encontré con este problema y quería encontrar algo sobre el rendimiento, pero no pude, así que escribió un guión de evaluación comparativa por mi cuenta:

% 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 

Como puede ver, la solución usando A = A(A ~= 0) es el más rápido de los dos :)

4

A menudo terminaba haciendo cosas como esta. Por lo tanto, traté de escribir una función simple que 'recorta' los elementos no deseados de una manera fácil. Esto convierte a la lógica de MATLAB un poco al revés, pero se ve bien:

b = snip(a,'0') 

se puede encontrar el archivo de función en: http://www.mathworks.co.uk/matlabcentral/fileexchange/41941-snip-m-snip-elements-out-of-vectorsmatrices

También funciona con todos los demás 'x', o lo que sea nan elementos.

+6

Ese es un poderoso martillo para adornar a una diminuta mosca ... – Shai

2

¿Por qué no solo, a=a(~~a) o a(~a)=[]. Es equivalente a los otros enfoques, pero ciertamente menos golpes de tecla.

2

datos

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

hacer

aa=nonzeros(a)' 

Resultado

aa=[3 7 10 3 1 7 7 1 7 4] 
+0

¿Por qué no hacer que esta publicación sea mejor ?: agregue un enlace a la documentación y uso de resaltado adecuado para su código – Sjon

+0

¡Creo que esta es una gran respuesta! Sería bueno obtener una comparación con otras propuestas. –

2

Usted podría utilizar escasa (a), que volvería

(1,2) 1

(1,4) 3

Esto le permite mantener la información sobre dónde solían estar sus entradas distintas de cero.

Cuestiones relacionadas