Menu

Spalten hinzufügen und transformieren in R (mutate und Base R)

Wie man Data-Frame-Spalten hinzufügt, transformiert und löscht: df$new <- ..., ifelse() für bedingte Spalten, transform() und dplyr's mutate() mit case_when().

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

Eine Spalte hinzufügen: df$new <- wert

Um in Base R eine Spalte hinzuzufügen, weist man einem Namen zu, der noch nicht existiert. Der Wert wird üblicherweise aus vorhandenen Spalten berechnet:

Zwei Dinge sind passiert. orders$total bekam einen vollständigen Vektor - price * qty wird für jede Zeile auf einmal berechnet, weil Arithmetik in R vektorisiert ist. orders$currency bekam einen Einzelwert, den R auf alle vier Zeilen recycelt hat. Jede andere Länge ist ein Fehler (replacement has 3 rows, data has 4) - R schützt dich damit vor einer falsch ausgerichteten Spalte.

Das funktioniert, weil ein Data Frame eine Liste gleich langer Spalten ist - die Zuweisung eines neuen benannten Elements lässt die Liste wachsen. Die Data-Frames-Doku erklärt dieses Modell im Detail.

Bedingte Spalten: ifelse()

Eine Spalte, deren Wert von einer Bedingung abhängt, will ifelse() - den vektorisierten Verwandten von if. Es nimmt einen ganzen Vektor von Bedingungen und liefert einen Wert pro Zeile:

Warum kein einfaches if? Weil if genau ein TRUE/FALSE auswertet - bekommt es eine Spalte, wirft es einen Fehler (the condition has length > 1). ifelse(test, yes, no) prüft jedes Element und wählt pro Zeile. Für drei oder mehr Ergebnisse kann man verschachteln:

Zwei Ebenen tief zu verschachteln ist in Ordnung; ab drei wird es zur Pyramide - genau dafür wurde dplyr's case_when() (unten) gebaut. Das if/else für Einzelwerte wird in der if-else-Doku behandelt.

Mehrere Spalten auf einmal: transform()

Base R's transform() fügt mehrere Spalten in einem Aufruf hinzu, mit nackten Spaltennamen:

Beachte, dass transform() einen neuen Data Frame zurückgibt - man muss das Ergebnis zurückweisen, während df$new <- ... direkt verändert. Eine Einschränkung: Die Ausdrücke innerhalb eines transform()-Aufrufs sehen einander nicht, discount = ifelse(total > 50, ...) schlägt dort also fehl (total existiert noch nicht). Mach es in zwei Schritten - oder mit mutate(), das es erlaubt.

Verändern vs. Erstellen

Dieselbe Zuweisungssyntax überschreibt eine bestehende Spalte - ob die Spalte schon existierte, ist der einzige Unterschied:

Hier lohnt sich ein Innehalten: R warnt nicht, wenn man eine Spalte überschreibt. Ein Tippfehler wie df$prise <- round(df$price, 2) erstellt stillschweigend eine neue Spalte, statt die alte zu korrigieren. Nach einer Transformation den Frame per print() oder str() prüfen und bestätigen, dass man das geändert hat, was man wollte.

Eine Spalte löschen

Zum Löschen NULL zuweisen:

Die Spalte ist weg, ohne Zeremonie. Um mehrere zu entfernen, ist df[, c("a", "b")] (behalten, was man aufführt) meist klarer als wiederholte NULLs.

Der dplyr-Weg: mutate()

dplyr's Verb für all das Obige ist mutate(). Die Snippets unten sind statisch - die Sandbox führt nur Base R aus -, aber so sehen dieselben Operationen aus:

library(dplyr)

orders |>
    mutate(
        total    = price * qty,
        big      = total > 50        # can use total, defined one line up
    )

Zwei Vorteile gegenüber Base R. Erstens können Spalten, die im selben mutate() definiert werden, aufeinander verweisen, der Reihe nach - genau das, was transform() verweigert. Zweitens sind die bedingten Helfer besser als verschachteltes ifelse():

students |>
    mutate(
        grade = if_else(score >= 60, "pass", "fail"),
        band  = case_when(
            score >= 85 ~ "high",
            score >= 60 ~ "mid",
            .default    = "low"
        )
    )

if_else() ist ein strengeres ifelse() (beide Zweige müssen denselben Typ haben - das fängt echte Bugs). case_when() liest sich als flache Liste von bedingung ~ wert-Paaren, die von oben nach unten geprüft werden, mit .default als Rückfall - der lesbare Ersatz für die ifelse()-Pyramide. Wie jedes dplyr-Verb gibt mutate() einen neuen Data Frame zurück; siehe die dplyr-Einführung dazu, wie es sich mit dem Rest verkettet.

Was du mitnimmst

  • df$new <- ausdruck fügt eine Spalte hinzu; der Ausdruck läuft für alle Zeilen auf einmal.
  • ifelse(test, yes, no) baut bedingte Spalten; ein einfaches if kann das nicht.
  • transform() fügt mehrere Spalten pro Aufruf hinzu, aber sie sehen einander nicht; mutate() kann das.
  • Dieselbe Zuweisung überschreibt stillschweigend - nach einer Transformation die Schreibweise prüfen.
  • df$col <- NULL entfernt eine Spalte; case_when() ersetzt verschachtelte ifelse()-Pyramiden.

Als Nächstes: Spalten umbenennen - names(), das robuste Base-Idiom und dplyr's rename().

Häufig gestellte Fragen

Wie füge ich einem Data Frame in R eine neue Spalte hinzu?

Weise einem Spaltennamen zu, der noch nicht existiert: df$total <- df$price * df$qty. R erstellt die Spalte an Ort und Stelle. Der Wert kann ein Einzelwert sein (der auf jede Zeile recycelt wird) oder ein aus anderen Spalten berechneter Vektor, solange seine Länge zur Zeilenanzahl passt.

Wie erstelle ich eine bedingte Spalte in R?

Verwende das vektorisierte ifelse(): df$grade <- ifelse(df$score >= 60, "pass", "fail") prüft alle Zeilen auf einmal. Kein einfaches if verwenden - das behandelt eine einzelne Bedingung, keine Spalte. Für mehr als zwei Ergebnisse ifelse()-Aufrufe verschachteln oder dplyr's case_when() nutzen.

Was macht mutate() in R?

mutate() ist dplyr's Verb zum Hinzufügen oder Transformieren von Spalten: df |> mutate(total = price * qty) gibt eine Kopie des Data Frames mit der neuen Spalte zurück. Es kann mehrere Spalten in einem Aufruf definieren, und spätere Spalten können frühere aus demselben mutate verwenden.

Wie lösche ich eine Spalte aus einem Data Frame in R?

Weise ihr NULL zu: df$notes <- NULL entfernt die Spalte direkt. In dplyr gibt select(-notes) eine Kopie ohne sie zurück.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S