Menu

Matrizen in R: matrix(), cbind, rbind und Matrixrechnung

Wie du Matrizen mit matrix(), cbind() und rbind() baust, Zeilen und Spalten indizierst und elementweises * sauber von echter Matrixmultiplikation %*% trennst.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Eine Matrix ist ein Vektor mit Dimensionen

Eine Matrix ist in R ein Rechteck aus Werten - Zeilen und Spalten -, in dem jede Zelle denselben Typ hält, meist Zahlen. Unter der Haube ist sie buchstäblich ein Vektor mit angehängtem dim-Attribut, was das meiste ihres Verhaltens erklärt: durchgehend ein Typ, überall vektorisierte Rechnung.

Du baust eine, indem du einen Vektor mit matrix() umformst:

Sechs Werte, zwei Zeilen - R rechnet aus, dass drei Spalten nötig sind. dim() meldet beide Dimensionen auf einmal als 2 3; nrow() und ncol() geben sie getrennt.

Schau dir die ausgegebene Matrix genau an: Die Werte laufen 1 2 die erste Spalte hinunter, dann 3 4 die nächste. R füllt Matrizen standardmäßig spaltenweise. Wenn deine Daten zeilenweise gelesen werden - so schreiben Menschen sie üblicherweise -, sag es mit byrow = TRUE:

Jetzt lautet die erste Zeile 1 2 3. byrow = TRUE zu vergessen erzeugt keinen Fehler - es gibt dir still eine transponiert wirkende Anordnung derselben Zahlen, mach es dir also zur Gewohnheit, das ausgegebene Layout zu prüfen, wann immer du eine Matrix aus Rohwerten konstruierst.

Indexierung: m[Zeile, Spalte]

Matrixindexierung nimmt zwei Positionen in einem Klammerpaar, die Zeile vor dem Komma, die Spalte danach - beide ab 1 gezählt:

Eine Position leer zu lassen bedeutet "alle davon": m[1, ] ist die ganze erste Zeile, m[, 2] die ganze zweite Spalte. Beachte, dass beide als schlichte Vektoren zurückkommen - R verwirft die Dimension, die auf Größe 1 zusammenfiel. Das ist interaktiv bequem und im Code eine Falle, denn eine Funktion, die eine Matrix erwartet, verschluckt sich am Vektor. Bitte R mit drop = FALSE, die Form zu behalten:

dim() meldet nun 1 3 - immer noch eine Matrix. Wann immer du in einer Funktion eine einzelne Zeile oder Spalte herausschneidest, schreib drop = FALSE; der Bug, den das verhindert (Code, der bei breiten Daten funktioniert und bei einspaltigen bricht), ist ein elend aufzuspürender.

Logische Masken funktionieren hier ebenfalls: m[m > 3] gibt alle Zellen über 3 als Vektor zurück.

Bauen mit cbind() und rbind()

Statt einen langen Vektor umzuformen, kannst du eine Matrix aus Teilen zusammensetzen: cbind() bindet Vektoren als Spalten zusammen, rbind() als Zeilen. Dieselben Funktionen erweitern auch eine bestehende Matrix:

Die Namen reisen mit den Vektoren mit: cbind() hat heights und weights automatisch als Spaltennamen genutzt, was die ausgegebene Matrix lesbar hält. Beide Funktionen bestehen darauf, dass die Längen zusammenpassen (mit Recycling bei Werten der Länge 1); einen Vektor der Länge 3 an eine 4-zeilige Matrix zu binden erzeugt eine Warnung.

Spalten- und Zeilennamen lassen sich auch direkt über colnames(m) <- ... und rownames(m) <- ... setzen, danach kannst du über Namen indizieren: people[, "weights"].

Elementweises * vs. echte Matrixmultiplikation %*%

Hier ist die Unterscheidung, die in diesem ganzen Artikel am wichtigsten ist. R hat zwei Multiplikationsoperatoren für Matrizen, und sie berechnen völlig verschiedene Dinge:

  • a * a ist elementweise: jede Zelle multipliziert mit der passenden Zelle. 1 2 3 4 werden zu 1 4 9 16, in derselben Form angeordnet. Das ist bloß vektorisierte Arithmetik, dasselbe *, das du auf Vektoren nutzt.
  • a %*% a ist Matrixmultiplikation aus der linearen Algebra - jede Ergebniszelle ist eine Zeile der ersten Matrix mal eine Spalte der zweiten, aufsummiert. Dieselbe Eingabe ergibt 7 10 15 22: völlig andere Zahlen.

Führ den Ausschnitt aus und vergleiche die beiden Ausgaben nebeneinander; sie bei identischer Eingabe abweichen zu sehen ist das, was die Unterscheidung haften lässt. Schreibst du *, wo die Mathematik %*% verlangt, warnt R dich nicht - bei quadratischen Matrizen sind die Formen so oder so kompatibel -, du bekommst schlicht falsche Zahlen. In Statistikcode (Kovarianzmatrizen, Algebra linearer Modelle) ist das einer der klassischen stillen Bugs.

t() transponiert - vertauscht Zeilen und Spalten - und taucht ständig neben %*% auf, weil Matrixmultiplikation übereinstimmende innere Dimensionen braucht:

Der Vollständigkeit halber: solve(m) invertiert eine Matrix, und %*% mit einem Vektor behandelt diesen als einspaltige Matrix. Tiefer muss die meiste Datenarbeit nicht gehen.

Zeilen- und Spaltenzusammenfassungen

Über Zeilen und Spalten zu summieren oder zu mitteln ist so verbreitet, dass R eigene, schnelle Funktionen dafür mitbringt:

rowSums() verdichtet jede Zeile zu einer Zahl (hier 6 15), colSums() jede Spalte (5 7 9), und die Means-Varianten mitteln stattdessen. Bevorzuge diese gegenüber selbstgebauten Schleifen oder auch apply(m, 1, sum) - sie sind klarer und schneller. Für Zusammenfassungen, die diese vier nicht abdecken (etwa ein Maximum je Spalte), ist die apply-Familie das allgemeine Werkzeug: apply(m, 2, max).

Matrix oder Data Frame?

Beide sind rechteckig - wozu greifst du also?

  • Matrix: jede Zelle derselbe Typ, und die Mathematik zählt. Numerische Berechnung, lineare Algebra, Distanzberechnungen, bildartige Gitter. Matrizen sind schlanker und ihre Operationen schneller, gerade wegen der Ein-Typ-Garantie.
  • Data Frame: Spalten verschiedener Typen - Namen neben Altersangaben neben logischen Flags. Das sind reale Tabellendaten, und das erwarten nahezu alle Datenanalysefunktionen.

Eine gute Regel: Würdest du es natürlicherweise in einer Tabellenkalkulation mit benannten, gemischten Spalten öffnen, ist es ein Data Frame. Ist es ein Zahlengitter, auf dem du Algebra betreiben willst, ist es eine Matrix. Die Umwandlung dazwischen ist einfach (as.matrix(), as.data.frame()) - aber as.matrix() auf einem Data Frame mit irgendeiner Textspalte konvertiert alles zu character, wandle also nur die numerischen Spalten um.

Was du mitnimmst

  • Eine Matrix ist ein Vektor mit Dimensionen: durchgehend ein Typ, gebaut mit matrix(data, nrow, ncol) - und sie füllt spaltenweise, sofern du nicht byrow = TRUE übergibst.
  • Indizieren als m[row, col]; eine leere Position bedeutet "alle"; ergänze drop = FALSE, wenn du im Code einzelne Zeilen oder Spalten herausschneidest.
  • cbind() und rbind() setzen Matrizen aus Vektoren zusammen oder erweitern bestehende.
  • * ist elementweise, %*% ist echte Matrixmultiplikation - dieselbe Eingabe, andere Antworten, keine Warnung.
  • rowSums() / colSums() / rowMeans() / colMeans() erledigen die Alltagszusammenfassungen.

Als Nächstes: Faktoren - wie R kategoriale Daten darstellt und welche Fallen damit einhergehen.

Häufig gestellte Fragen

Wie erstellt man eine Matrix in R?

matrix(1:6, nrow = 2) formt einen Vektor zu 2 Zeilen und 3 Spalten um und füllt dabei spaltenweise. Ergänze byrow = TRUE, um stattdessen zeilenweise zu füllen. Du kannst eine Matrix auch aus Vektoren zusammensetzen: cbind() klebt sie als Spalten, rbind() als Zeilen.

Was ist der Unterschied zwischen * und %*% in R?

* multipliziert elementweise - jede Zelle mal die passende Zelle, die Formen müssen zusammenpassen. %*% ist die echte Matrixmultiplikation der linearen Algebra (Zeilen mal Spalten, also müssen die inneren Dimensionen übereinstimmen). Sie liefern auf denselben Matrizen völlig verschiedene Ergebnisse, und * zu nutzen, wo du %*% meintest, ist ein klassischer stiller Bug.

Wie holt man in R eine einzelne Zeile oder Spalte einer Matrix?

Lass die andere Position leer: m[1, ] ist die erste Zeile, m[, 2] die zweite Spalte. Beide kommen standardmäßig als schlichte Vektoren zurück. Ergänze drop = FALSE - wie in m[1, , drop = FALSE] -, um das Ergebnis als einzeilige oder einspaltige Matrix zu behalten, was zählt, wenn späterer Code zwei Dimensionen erwartet.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S