Frage

Ich möchte eine Funktion auf alle Spalten in einer Matrix mit MATLAB anzuwenden. Zum Beispiel würde ich in der Lage sein mag jede Spalte einer Matrix zu rufen glätten, statt mit glatten die Matrix als Vektor behandeln (die das Standardverhalten, wenn Sie rufen smooth(matrix)).

Ich bin sicher, es muss eine idiomatische Weg, dies zu tun, aber ich kann es nicht finden, also habe ich eine map_column Funktion definiert:

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

, die ich nennen kann mit:

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

Gibt es etwas falsch mit diesem Code? Wie könnte ich es verbessern?

War es hilfreich?

Lösung

Ihre Lösung ist in Ordnung.

Beachten Sie, dass horizcat eine erhebliche Leistungseinbuße für große Matrizen zumutet. Es macht den Code O (N ^ 2) anstelle von O (N). Für eine 100x10,000 Matrix nimmt Ihre Implementierung 2.6s auf meiner Maschine, die horizcat ein 64.5s nimmt. Für eine 100x5000 Matrix nimmt die horizcat Implementierung 15.7s.

Wenn Sie möchten, können Sie Ihre Funktion ein wenig verallgemeinern und machen es in der Lage sein, über die endgültige Dimension zu durchlaufen oder auch über beliebige Dimensionen (nicht nur Spalten).

Andere Tipps

Die MATLAB „für“ Anweisung Schleifen tatsächlich über die Spalten, was auch immer ist geliefert - in der Regel führt dies nur in einer Folge von Skalaren seit dem Vektor ging in für (wie in Ihrem Beispiel oben) ist ein Zeilenvektor. Dies bedeutet, dass Sie den obigen Code wie folgt umschreiben kann:

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

Wenn func keine Spaltenvektor zurück, dann können Sie so etwas wie hinzufügen

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

zu zwingen, sie in eine Spalte.

Vielleicht könnten Sie immer verwandeln die Matrix mit dem "Betreiber und dann das Ergebnis Transformation zurück.

smoothed = smooth(input', 9)';

Das zumindest arbeitet mit der FFT-Funktion.

Ein Weg, um eine implizite Schleife über die Spalten einer Matrix zu verursachen, wird cellfun zu verwenden. Das heißt, müssen Sie zuerst die Matrix zu einem Zellenfeld umwandeln, wird jede Zelle eine Spalte halten. Dann rufen cellfun. Zum Beispiel:

A = randn(10,5);

Sehen Sie hier, dass ich die Standardabweichung für jede Spalte berechnet haben.

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

ans =
      0.78681       1.1473      0.89789      0.66635       1.3482

Natürlich sind viele Funktionen in MATLAB bereits eingerichtet auf Zeilen oder Spalten eines Arrays zu arbeiten, wie der Benutzer angibt. Dies gilt für std natürlich, aber das ist eine bequeme Art und Weise, dass cellfun zu testen erfolgreich gearbeitet.

std(A,[],1)

ans =
      0.78681       1.1473      0.89789      0.66635       1.3482

Vergessen Sie nicht, das Ergebnis Matrix vorzubelegen, wenn Sie mit großen Matrizen handelt. Ansonsten Ihre CPU viele Zyklen verbringen wiederholt Neuzuweisung der Matrix jedes Mal, es fügt eine neue Zeile / Spalte.

Wenn dies ein gemeinsamer Anwendungsfall für Ihre Funktion, wäre es vielleicht eine gute Idee sein, die Funktion Iterierte durch die Spalten automatisch zu machen, wenn der Eingang nicht ein Vektor ist.

Dies ist nicht genau Ihr Problem lösen, aber es würde die Funktionen der Nutzung vereinfachen. In diesem Fall sollte die Ausgabe eine Matrix sein, auch.

Sie können auch die Matrix zu einer langen Spalte Transformation von m(:,:) = m(:) verwenden. Allerdings ist es auf Ihre Funktion hängt ab, wenn dies sinnvoll ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top