Pregunta

Quiero aplicar una función a todas las columnas en una matriz con MATLAB. Por ejemplo, me gustaría poder llamar sin problemas en cada columna de una matriz, en lugar de tener un tratamiento suave de la matriz como un vector (que es el comportamiento predeterminado si llama a suave (matriz) ).

Estoy seguro de que debe haber una forma más idiomática de hacer esto, pero no puedo encontrarlo, así 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?

¿Fue útil?

Solución

Tu solución está bien.

Tenga en cuenta que horizcat impone una penalización de rendimiento sustancial 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, el horizcat toma 64.5s. Para una matriz de 100x5000, la implementación de horizcat toma 15.7s.

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

Otros consejos

El MATLAB " para " en realidad, la declaración recorre las columnas de lo que se suministra; normalmente, esto solo da como resultado una secuencia de escalares, ya que el vector que pasa a (como en el ejemplo anterior) es un vector de fila. Esto significa que puede volver a escribir el código anterior de esta manera:

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

Si func no devuelve un vector de columna, entonces puede agregar algo como

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

para forzarlo en una columna.

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

smoothed = smooth(input', 9)';

Eso al menos funciona con la función fft.

Una forma de provocar un bucle implícito a través de las columnas de una matriz es usar cellfun. Es decir, primero debe convertir la matriz en una matriz de celdas, cada celda tendrá una columna. Entonces 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,size(A,1),ones(1,size(A,2))))

ans =
      0.78681       1.1473      0.89789      0.66635       1.3482

Por supuesto, muchas funciones en MATLAB ya están configuradas para trabajar en filas o columnas de una matriz como lo indica el usuario. Por supuesto, esto se aplica a la norma estándar, pero es una forma conveniente de probar que cellfun funcionó correctamente.

std(A,[],1)

ans =
      0.78681       1.1473      0.89789      0.66635       1.3482

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

Si este es un caso de uso común para su función, tal vez sería una buena idea hacer que la función se repita en 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 debe ser una matriz.

También puede transformar la matriz en una columna larga utilizando m (:, :) = m (:) . Sin embargo, depende de tu función si esto tendría sentido.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top