2008-10-19 32 views
8

Quiero aplicar una función a todas las columnas en una matriz con MATLAB. Por ejemplo, me gustaría poder llamar sin problemas a cada columna de una matriz, en lugar de tratar suavemente la matriz como un vector (que es el comportamiento predeterminado si llamas suavemente (matriz)).¿Cuál es la mejor forma de recorrer las columnas de una matriz en MATLAB?

Estoy seguro de que debe haber una manera más idiomática para hacer esto, pero no puedo encontrarlo, por lo que he definido una función map_column:

function result= map_column(m, func) 
    result= m; 
    for col= 1:size(m,2) 
     result(:,col)= func(m(:,col)); 
    end 
end 

que puedo llamar con:

smoothed= map_column(input, @(c) (smooth(c, 9))); 

¿Hay algún problema con este código? ¿Cómo podría mejorarlo?

Respuesta

3

Su solución está bien.

Tenga en cuenta que horizcat exige una importante penalización de rendimiento para matrices grandes. Hace que el código sea O (N^2) en lugar de O (N). Para una matriz de 100x10,000, su implementación toma 2.6s en mi máquina, la horizcat toma 64.5s. Para una matriz de 100x5000, la implementación de horizcat toma 15.7s.

Si lo desea, podría generalizar un poco su función y hacerla iterar sobre la dimensión final o incluso sobre las dimensiones arbitrarias (no solo las columnas).

0

Si este es un caso de uso común para su función, quizás sería una buena idea hacer que la función itere a través de las columnas automáticamente si la entrada no es un vector.

Esto no resuelve exactamente su problema, pero simplificaría el uso de las funciones. En ese caso, la salida también debería ser una matriz.

También puede transformar la matriz en una columna larga usando m(:,:) = m(:). Sin embargo, depende de su función si esto tuviera sentido.

2

Tal vez siempre puedas transformar la matriz con el operador 'y luego transformar el resultado.

smoothed = smooth(input', 9)'; 

Que al menos funciona con la función fft.

+0

Esto no funciona para la función suave. Si pasa una matriz lisa, la trata como un vector grande. Sin embargo, este método sería conveniente para algunas otras funciones. – dmnd

10

La instrucción MATLAB "para" en realidad pasa por encima de las columnas de lo que se suministre; normalmente, esto resulta en una secuencia de escalares desde que el vector pasó (como en el ejemplo anterior) es un vector de fila. Esto significa que puede volver a escribir el código anterior como esto:

function result = map_column(m, func) 
    result = []; 
    for m_col = m 
     result = horzcat(result, func(m_col)); 
    end 

Si func no devuelve un vector columna, a continuación, puede añadir algo como

f = func(m_col); 
result = horzcat(result, f(:)); 

a la fuerza en una columna.

1

No olvide preasignar la matriz de resultados si se trata de matrices grandes. De lo contrario, su CPU pasará muchos ciclos reasignando repetidamente la matriz cada vez que agregue una nueva fila/columna.

1

Una forma de causar un bucle implícito en las columnas de una matriz es usar cellfun. Es decir, primero debe convertir la matriz en una matriz de celdas, cada celda contendrá una columna. Luego llama a cellfun.Por ejemplo:

A = randn (10,5);

Vea que aquí he calculado la desviación estándar para cada columna.

cellfun (@ std, mat2cell (A, tamaño (A, 1), los (1, tamaño (A, 2))))

ans = 0,78681 1,1473 0.89789 0,66635 1,3482

De Por supuesto, muchas funciones en MATLAB ya están configuradas para trabajar en filas o columnas de una matriz como lo indica el usuario. Esto es cierto de std, por supuesto, pero esta es una forma conveniente de probar que cellfun funcionó correctamente.

std (A, [], 1)

ans = 0,78681 1,1473 0,89789 0,66635 1,3482

Cuestiones relacionadas