Quiero aplicar una función a todas las columnas de una matriz con MATLAB. Por ejemplo, me gustaría ser capaz de llamar a lisa en cada columna de una matriz, en lugar de tener suavizar el tratamiento de la matriz como un vector (que es el comportamiento por defecto si usted llama smooth(matrix)).

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

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 nada malo con este código? ¿Cómo podría mejorar?

OriginalEl autor |

6 Comentarios

  1. 3

    Tu solución es buena.

    Nota que horizcat impone una penalización de rendimiento considerable para matrices grandes. Esto hace que el código sea O(N^2) en lugar de O(N). Para un 100×10,000 de la matriz, su implementación se lleva a 2.6 s en mi máquina, el horizcat uno toma 64.5 s. Para un 100×5000 de la matriz, la horizcat implementación se lleva a 15.7 s.

    Si lo desea, usted podría generalizar su función un poco y hacer que éste sea capaz de iterar sobre la dimensión final o incluso a través de dimensiones arbitrarias (no sólo de las columnas).

    OriginalEl autor

  2. 9

    MATLAB «para la» declaración de hecho se repite a lo largo de las columnas de lo que sea suministrado normalmente, esto sólo resulta en una secuencia de escalares ya que el vector que pasa por (como en el ejemplo anterior) es un vector fila. Esto significa que usted puede volver a escribir el código anterior como este:

    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, entonces usted puede agregar algo como

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

    a la fuerza en una columna.

    OP código pre-asigna el result de la matriz, este código no. En lugar de ello, crece la matriz de cada iteración, lo que acarrea una gran pena. Uno siempre debe tratar de pre-asignar matrices en MATLAB.

    OriginalEl autor

  3. 2

    Tal vez siempre se puede transformar la matriz con el ‘ operador y, a continuación, transformar el resultado de la espalda.

    smoothed = smooth(input', 9)';

    Que al menos funciona con la función fft.

    Esto no funciona para la función suave. Si usted pase suave de una matriz, lo trata como un gran vector. Este método sería conveniente para algunas otras funciones, aunque.
    ' es el conjugado complejo de incorporar. Si el objetivo es intercambiar las dos dimensiones de la matriz, utilice .'.

    OriginalEl autor

  4. 2

    Una manera de hacer que un bucle implícito a través de las columnas de una matriz es el uso de cellfun. Es decir, primero debe convertir la matriz en una matriz de células, cada célula se mantenga una columna. A continuación, llame a cellfun. Por ejemplo:

    A = randn(10,5);

    Ver 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 de las funciones en MATLAB ya están configurados para trabajar en filas o columnas de una matriz como el usuario indica. Esto es cierto de la ets de curso, pero esta es una manera conveniente para probar que cellfun trabajado con éxito.

    std(A,[],1)
    
    ans =
          0.78681       1.1473      0.89789      0.66635       1.3482
    Esta solución es ACEPTAR, sólo requiere algo de memoria adicional. Para coincidir con la utilización de la OP, agregar 'UniformOutput',false a la cellfun llamada, luego concatenar todos los que (esperemos) vectores columna que se produce de nuevo en una matriz utilizando horzcat(result{:}) o, equivalentemente,cat(2,result{:}). Esta solución es aproximadamente igual de eficiente como el código de la OP, como cellfun se implementa mediante un bucle en una forma muy similar.

    OriginalEl autor

  5. 1

    No olvide asignar previamente el resultado de la matriz, si se trata de matrices grandes. De lo contrario, la CPU va a gastar un montón de ciclos repetidamente re-asignación de la matriz cada vez que se agrega una nueva fila/columna.

    OriginalEl autor

  6. 0

    Si se trata de un caso de uso para su función, tal vez sería una buena idea para hacer la función de iteración a través de las columnas automáticamente si la entrada no es un vector.

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

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

    OriginalEl autor

Dejar respuesta

Please enter your comment!
Please enter your name here