Domanda

Voglio applicare una funzione a tutte le colonne in una matrice con MATLAB. Ad esempio, vorrei essere in grado di chiamare smooth su ogni colonna di una matrice, anziché avere smooth tratta la matrice come un vettore (che è il comportamento predefinito se chiami smooth (matrice) ).

Sono sicuro che ci deve essere un modo più idiomatico per farlo, ma non riesco a trovarlo, quindi ho definito una funzione map_column :

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

con cui posso chiamare:

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

C'è qualcosa di sbagliato in questo codice? Come potrei migliorarlo?

È stato utile?

Soluzione

La tua soluzione va bene.

Notare che horizcat applica una sostanziale penalità prestazionale per matrici di grandi dimensioni. Rende il codice essere O (N ^ 2) invece di O (N). Per una matrice 100x10.000, l'implementazione richiede 2.6s sulla mia macchina, quella horizcat richiede 64.5s. Per una matrice 100x5000, l'implementazione di horizcat richiede 15.7s.

Se lo desideri, potresti generalizzare un po 'la tua funzione e renderla in grado di iterare sulla dimensione finale o anche su dimensioni arbitrarie (non solo colonne).

Altri suggerimenti

MATLAB " per " L'istruzione in realtà scorre sopra le colonne di qualsiasi cosa venga fornita - normalmente, questo si traduce in una sequenza di scalari poiché il vettore passato per (come nell'esempio sopra) è un vettore di riga. Ciò significa che puoi riscrivere il codice sopra in questo modo:

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

Se func non restituisce un vettore di colonna, è possibile aggiungere qualcosa di simile

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

per forzarlo in una colonna.

Forse potresti sempre trasformare la matrice con l'operatore 'e poi riconvertire il risultato.

smoothed = smooth(input', 9)';

Questo funziona almeno con la funzione fft.

Un modo per causare un ciclo implicito attraverso le colonne di una matrice è usare cellfun. Cioè, devi prima convertire la matrice in un array di celle, ogni cella conterrà una colonna. Quindi chiama cellfun. Ad esempio:

A = randn(10,5);

Vedi che qui ho calcolato la deviazione standard per ogni colonna.

cellfun(@std,mat2cell(A,size(A,1),ones(1,size(A,2))))

ans =
      0.78681       1.1473      0.89789      0.66635       1.3482

Naturalmente, molte funzioni in MATLAB sono già impostate per funzionare su righe o colonne di un array come indicato dall'utente. Questo vale ovviamente per std, ma è un modo conveniente per testare che cellfun ha funzionato correttamente.

std(A,[],1)

ans =
      0.78681       1.1473      0.89789      0.66635       1.3482

Non dimenticare di preallocare la matrice dei risultati se hai a che fare con matrici di grandi dimensioni. Altrimenti la tua CPU impiegherà molti cicli ri-allocando ripetutamente la matrice ogni volta che aggiunge una nuova riga / colonna.

Se questo è un caso d'uso comune per la tua funzione, sarebbe forse una buona idea far iterare automaticamente la funzione attraverso le colonne se l'input non è un vettore.

Questo non risolve esattamente il tuo problema ma semplificherebbe l'utilizzo delle funzioni. In tal caso, anche l'output dovrebbe essere una matrice.

Puoi anche trasformare la matrice in una colonna lunga usando m (:, :) = m (:) . Tuttavia, dipende dalla tua funzione se questo ha senso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top