...

Datenmanagement in R

Einleitung

In diesem Beitrag möchte ich Dich durch das Datenmanagement in R führen. Falls Du schon mal mit R gearbeitet hast, hast Du sicher gemerkt, wie mächtig dieses Tool ist – und manchmal auch ein bisschen einschüchternd. Aber keine Sorge, wir gehen das Ganze locker an: Schritt für Schritt, mit Praxisbeispielen und einer Prise Humor.

Wir sprechen über das Einlesen von Daten, das Aufbereiten und Transformieren, über den Umgang mit fehlenden Werten, das Filtern und Kodieren sowie über das Speichern und Exportieren von Daten in R. Das klingt nach einer Menge, aber glaub mir: Wenn Du einmal den Dreh raus hast, wirst Du Dich fragen, wie Du jemals ohne diese Möglichkeiten ausgekommen bist.

R ist open source, also kostenlos, und bietet eine große Auswahl an Paketen (Libraries), die Dir das Leben leichter machen. Das Beste: Du kannst Deinen gesamten Datenworkflow von A bis Z in R abdecken – vom Datenimport, über die Datenbereinigung bis hin zu den finalen Auswertungen und Grafiken.

Egal, ob es CSV-Dateien, Excel-Sheets, Datenbanken oder sogar Web-APIs sind – R hilft Dir, alles unter einen Hut zu bekommen. Und weil Du alles in Skripten bzw. R Markdown Dokumenten festhalten kannst, ist Dein Vorgehen reproduzierbar. Das ist nicht nur praktisch für Dich selbst (Stichwort: „Ich hab doch letztes Jahr was Ähnliches gemacht…“), sondern auch für die Zusammenarbeit mit anderen.

Grundlagen & Setup

Wichtige Pakete

Bevor es richtig losgeht, möchte ich kurz auf die Pakete eingehen, die ich besonders oft für Datenmanagement nutze. Es gibt unzählige Pakete in R, aber dplyr und readr (beide Teil des tidyverse) sind echte Allrounder. Falls Du mit Excel-Dateien arbeitest, ist readxl oft hilfreich. Um Daten aufzuräumen und zu transformieren, kommt man eigentlich an tidyr ebenfalls nicht vorbei.

Ein R-Paket (engl. package) ist eine Sammlung von Funktionen, Datensätzen und Dokumentationen, die für einen bestimmten Zweck entwickelt wurden. Wenn Du ein Paket installierst (install.packages("paketname")) und lädst (library(paketname)), stehen Dir dessen Funktionen im R-Umfeld zur Verfügung.

RStudio-Projekte & Verzeichnisse

Ich persönlich empfehle Dir, ein eigenes RStudio-Projekt einzurichten. Das ist super, weil Du damit gleich einen klaren, separaten Arbeitsplatz hast, in dem Dein kompletter Code, Deine Daten und Deine Ergebnisse liegen. So bist Du gleich gut organisiert.

  • Projekt anlegen: In RStudio oben rechts auf den Button klicken (oder über „File -> New Project…“).
  • Verzeichnisstruktur: Oft nutze ich Ordner wie data/ für Rohdaten, R/ für Skripte, output/ für Grafiken und Tabellen, docs/ für Berichte.

Wenn Du Deine Daten einliest, vermeidest Du absolute Pfade (z. B. C:\Benutzer\Du…) – stattdessen arbeitest Du mit relativen Pfaden. Das macht Dein Projekt portabel.

Daten einlesen

Nun zum Kernstück: Wie bekommen wir unsere Daten in R? Hier ein paar gängige Wege.

Einlesen von CSV/TXT

Die wohl häufigste Quelle sind CSV-Dateien (Comma-Separated Values) oder auch TSV (Tab-Separated Values). Dank des readr-Pakets (Teil vom tidyverse) geht das Ruckzuck:

# Ganz klassisch:
meine_daten <- read.csv("data/mein_datensatz.csv")

# Mit readr-Paket:
library(readr)
meine_daten <- read_csv("data/mein_datensatz.csv")

Der Vorteil von read_csv() ist, dass es etwas schneller sein kann und Du zusätzlich ein paar nette Optionen hast, z. B. mit col_types genau anzugeben, welcher Datentyp in welcher Spalte erwartet wird.

Tipp: Separator anpassen. Manchmal wird statt eines Kommas ein Semikolon ; verwendet. Achte daher ggf. auf Parameter wie sep = ";" (in der Basisfunktion read.csv2() schon voreingestellt).

Einlesen von Excel-Dateien

Hast Du Excel-Dateien, kannst Du das Paket readxl nutzen. Das ist ebenfalls sehr einfach zu verwenden:

library(readxl)
excel_daten <- read_excel("data/meine_exceldatei.xlsx",
                          sheet = "Tabelle1")

Hiermit liest Du den gewünschten „Sheet“ ein und bekommst ein Data Frame zurück. Du musst also nicht erst manuell in Excel zu CSV konvertieren, was Zeit spart und potenzielle Fehlbedienungen reduziert.

Weitere Formate

  • JSON: Mithilfe von Paketen wie jsonlite kannst Du JSON-Dateien einlesen.
  • SQL-Datenbanken: Mit DBI und RSQLite (oder anderen Treibern) kannst Du direkt auf Datenbanken zugreifen.
  • Web-APIs: Das Paket httr hilft beim Abfragen von REST-APIs (z. B. JSON-Antworten).

Kurz gesagt: Egal, welches Format Du hast – vermutlich existiert in R ein passendes Paket.

Datenaufbereitung und Transformation

Grundlegende Operationen mit dplyr

dplyr ist ein Paket, das Deine Daten wrangle-t, also strukturiert und aufbereitet. Die fünf wichtigsten „Helferlein“ von dplyr sind:

  1. filter() – Zeilen basierend auf einer Bedingung auswählen
  2. select() – Spalten auswählen oder umbenennen
  3. mutate() – Neue Spalten erstellen bzw. Variablen umkodieren
  4. arrange() – Datensätze sortieren
  5. summarise() + group_by() – Daten gruppiert zusammenfassen

Daten-Wrangling bezeichnet sämtliche Schritte, die notwendig sind, um „rohe“ Daten in ein Format zu bringen, das für Analysen oder Visualisierung geeignet ist. Also z. B. Aufräumen von Spalten, Umbenennen von Variablen, Zusammenführen einzelner Tabellen etc.

Beispiele für Transformation

Nehmen wir an, Du hast einen Datensatz meine_daten, der folgende Spalten hat:

  • id (einfach eine Laufnummer)
  • geschlecht (Werte: „m“, „w“)
  • alter (Alter in Jahren)
  • einkommen (in Euro)

Jetzt schauen wir uns dplyr-Funktionen an:

library(dplyr)

# 1) Filter: Nur Personen über 30
df_ueber30 <- meine_daten %>%
  filter(alter > 30)

# 2) Select: Nur Spalten id, alter und einkommen
df_einkommen <- meine_daten %>%
  select(id, alter, einkommen)

# 3) Mutate: Neue Variable 'alter_gruppe' anhand von alter
df_mutiert <- meine_daten %>%
  mutate(alter_gruppe = if_else(alter < 18, "Kind/Jugend",
                                if_else(alter < 65, "Erwachsen", 
                                        "Senior")))

Hier siehst Du, wie Du aus einer fortlaufenden Variable (Alter) kategorische Gruppen machst. Das ist „Kodierung“: Wir legen also aus einer Zahl eine Kategorie an.

Filterung und Sortierung

Nach dem Filtern willst Du vielleicht sortieren:

df_sortiert <- meine_daten %>%
  filter(!is.na(einkommen)) %>%    # Zeilen mit NA in einkommen ausschließen
  arrange(desc(einkommen))         # absteigend nach Einkommen sortieren

desc(einkommen) sorgt für absteigende Sortierung. Mit arrange(einkommen) wäre es aufsteigend.

Kodierung von Variablen

Mit R kannst Du Variablen sehr flexibel umkodieren. Angenommen, das Geschlecht sei „m“ oder „w“ – Du willst daraus Faktoren machen, z. B. „Männlich“, „Weiblich“:

df_kodiert <- meine_daten %>%
  mutate(geschlecht_factor = factor(geschlecht,
                                    levels = c("m", "w"),
                                    labels = c("Männlich", "Weiblich")))

Ein Faktor in R (engl. factor) ist eine spezielle Datenstruktur zur Speicherung von Kategorien. Anders als bei Character-Variablen hat jede Kategorie einen eigenen Level. Das ist für statistische Auswertungen hilfreich (z. B. lineare Modelle mit kategorischen Prädiktoren).

Kodierung kann auch bedeuten, dass Du neue Stufen hinzufügst, Werte zusammenfasst oder numerische Variablen in Klassen einteilst.

Umgang mit fehlenden Werten

Was sind fehlende Werte (NA)?

In R werden fehlende Werte als NA (Not Available) markiert. Wenn Du also einen Datensatz hast, in dem in einer Spalte bestimmte Einträge fehlen, wird das in R meist als NA gekennzeichnet.

NA steht für fehlende Information in R. Es bedeutet, dass der tatsächliche Wert nicht bekannt oder nicht definiert ist.

Erkennen von NA

# Gibt TRUE aus, wenn Wert fehlt
is.na(meine_daten$einkommen)

# Anzahl fehlender Werte in Spalte einkommen:
sum(is.na(meine_daten$einkommen))

Umgang mit NA in Berechnungen

Rechnest Du z. B. den Mittelwert:

mean(meine_daten$einkommen)
# [1] NA

R sagt NA, weil es nicht weiß, was es mit den fehlenden Werten anstellen soll. Du kannst Parameter wie na.rm = TRUE benutzen:

mean(meine_daten$einkommen, na.rm = TRUE)

So werden fehlende Werte ignoriert bei der Berechnung. Achte jedoch darauf, warum sie fehlen und ob Ignorieren sinnvoll ist.

Strategien für fehlende Werte

  • Einfaches Entfernen (na.omit() oder drop_na()): Du wirfst Zeilen raus, die NAs enthalten. Vorsicht, Du könntest wichtige Daten verlieren.
  • Imputation: Fehlende Werte werden geschätzt, z. B. durch Mittelwert, Median oder komplexere Methoden (multiple Imputation). Das ist eine weiterführende Methode, auf die wir hier im Einsteigerkurs nicht weiter eingehen werden.
  • Spezifische Behandlung: Manchmal trägt man einen eigenen Code (z. B. 9999) in Datensätzen für fehlende Werte ein. Dann muss man das in R aktiv konvertieren zu NA.

Datenexport und Speicherung

Wenn Du fertig mit dem Wrangling bist, willst Du Deine Daten vielleicht in einer anderen Form speichern oder auch Deinen finalen Datensatz an Kollegen schicken.

Export als CSV

write.csv(df_kodiert, "output/ergebnis.csv", row.names = FALSE)

Mit row.names = FALSE verhinderst Du, dass R eine zusätzliche Spalte für Zeilennamen anlegt.

Export als Excel

Hier gibt es mehrere Wege. Mit dem Paket writexl (leichtgewichtig, keine Java-Abhängigkeit) kannst Du einen Data Frame so speichern:

library(writexl)
write_xlsx(df_kodiert, "output/ergebnis.xlsx")

Alternativ bietet das Paket openxlsx oder xlsx ähnliche Funktionen. Auch dort kannst Du angeben, in welchem Sheet Du die Daten ablegen möchtest.

R-spezifische Formate: RDS und RData

  • RDS speichert ein einziges Objekt in einer Datei.
saveRDS(df_kodiert, file = "output/ergebnis.rds")
# Laden:
mein_obj <- readRDS("output/ergebnis.rds")
  • RData speichert mehrere Objekte in einer Datei.
save(df_kodiert, df_sortiert, file = "output/meine_objekte.RData")
# Laden:
load("output/meine_objekte.RData")

Diese Formate sind praktisch, weil sie Datentypen und Attribute (z. B. Faktoren) direkt erhalten. Das CSV-Format geht damit rudimentärer um.

Best Practices & Tipps

Projektstruktur & Dokumentation

  • Ordnerstruktur: Halte Deine Daten, Skripte, Funktionen, Outputs getrennt.
  • Namensgebung: Vermeide Leerzeichen und Sonderzeichen in Dateinamen. Besser: meine_daten_2023-01-01.csv.
  • Kommentare: Kommentiere, was Du machst, aber nicht zu redundante Sachen wie „Dies ist ein Mittelwert…“. Kurze, gezielte Erläuterungen helfen sehr, wenn Du den Code in einem halben Jahr wieder anschaust.

Erste Data-Quality-Checks

  • summary() gibt Dir einen groben Überblick, Minima, Maxima, Mittelwerte usw.
  • str() verrät Dir, welche Datentypen Du hast und wie viele Zeilen/Spalten vorliegen.
  • head() und tail() um einen Ausschnitt der Daten anzuzeigen.
  • Plots, z. B. Histogramme oder Boxplots, sind ebenfalls Gold wert, um Ausreißer aufzuspüren.

Ein Beispielcode für einen schnellen Plot:

plot(meine_daten$alter, meine_daten$einkommen,
     xlab = "Alter",
     ylab = "Einkommen (Euro)",
     main = "Streudiagramm Alter vs. Einkommen")

Oder moderner mit ggplot2:

library(ggplot2)

ggplot(meine_daten, aes(x = alter, y = einkommen)) +
  geom_point() +
  labs(title = "Alter vs. Einkommen",
       x = "Alter",
       y = "Einkommen (Euro)")

Fragen & Antworten (Q&A)

Im Folgenden gebe ich Dir ein kleines Frage-Antwort-Spiel, damit Du prüfen kannst, ob Du die wichtigen Punkte verstanden hast. Ich schreibe die Frage und gebe eine Beispielantwort, an der Du Dich orientieren kannst.

  1. Frage: Wie lese ich in R eine CSV-Datei namens daten.csv ein, wenn sie im Unterordner raw_data liegt?
    Antwort (Beispiel): Du kannst zuerst sicherstellen, dass Dein Working Directory stimmt (bzw. in einem RStudio-Projekt bist). Dann nutzt Du z. B.meine_daten <- read.csv("raw_data/daten.csv", sep = ",", header = TRUE) Oder mit dem readr-Paket:library(readr) meine_daten <- read_csv("raw_data/daten.csv") Wichtig ist, dass Du gegebenenfalls den richtigen Trenner (sep) angibst und header = TRUE, wenn Du Spaltennamen in der ersten Zeile hast.
  2. Frage: Was sind NA-Werte und wie kann ich sie beim Berechnen eines Mittelwerts ausschließen?
    Antwort (Beispiel): NA steht für fehlende Werte in R. Hast Du etwa bei meine_daten$einkommen fehlende Werte, dann musst Du beim Mittelwert sagen:mean(meine_daten$einkommen, na.rm = TRUE) Damit ignorierst Du alle fehlenden Werte und bekommst einen Mittelwert über die verfügbaren Daten.
  3. Frage: Wie kann ich eine numerische Variable in Kategorien aufsplitten (z. B. „jünger als 18“, „18-64“, „65 und älter“)?
    Antwort (Beispiel): In R gibt es mehrere Wege. Ein klassischer wäre mit if_else in dplyr:library(dplyr) df_neu <- df_alt %>% mutate(alter_klasse = case_when( alter < 18 ~ "Kind/Jugend", alter < 65 ~ "Erwachsen", TRUE ~ "Senior" )) So erstellst Du eine neue Spalte namens alter_klasse anhand vordefinierter Bedingungen.
  4. Frage: Wie exportiere ich meine aufbereiteten Daten als Excel-Datei?
    Antwort (Beispiel): Ich lade zuerst das Paket writexl:install.packages("writexl") # falls noch nicht installiert library(writexl) write_xlsx(meine_daten, "output/meine_daten.xlsx") Dadurch habe ich eine Excel-Datei im output-Ordner, die den Data Frame enthält.
  5. Frage: Was ist der Vorteil von saveRDS() im Vergleich zu write.csv()?
    Antwort (Beispiel): saveRDS() speichert das Objekt in einem R-spezifischen Binärformat und erhält dabei alle Informationen über Datentypen (z. B. Faktoren). Das Laden geht über readRDS(). Mit write.csv() verlierst Du teilweise Metadaten (z. B. die Factor-Level-Information). CSVs sind aber natürlich universeller, wenn Du Daten an Nicht-R-Nutzer geben willst.
  6. Frage: Wie gehe ich vor, wenn ich riesige Datensätze habe, die in den Arbeitsspeicher passen, aber alles etwas zäh läuft?
    Antwort (Beispiel): Ich könnte das Paket data.table ausprobieren, das super effizient für Filter- und Transformationsoperationen ist. Außerdem vielleicht meine Datensätze in ein performanteres Format wie Parquet (über das Paket arrow) bringen oder, falls es ganz groß ist, eine Datenbank-Anbindung via DBI und RSQLite nutzen.
  7. Frage: Was bringt mir ein RStudio-Projekt konkret?
    Antwort (Beispiel): Ein Projekt hilft Dir, Deine Dateien organisiert an einem Ort zu halten, die „Working Directory“-Thematik zu entschärfen (alles ist relativ zum Projektordner), und Du kannst leichter Versionskontrolle (Git) integrieren. Es ist quasi Dein eigener kleiner Container für Code, Daten und Ergebnisse.
  8. Frage: Wann sollte ich fehlende Werte entfernen und wann eher ersetzen?
    Antwort (Beispiel): Das hängt vom Kontext ab. Wenn Daten wirklich zufällig fehlen und Du genügend Beobachtungen hast, kann ein Löschen ok sein. Wenn es jedoch systematische Gründe fürs Fehlen gibt (z. B. bestimmte Gruppen), könnte das zu Verzerrungen führen. Dann lohnt es sich, Imputationsverfahren zu prüfen, z. B. Mittelwert-, Median-, oder komplexere multiple Imputation.

Fazit

Datenmanagement in R klingt erst mal umfangreich, aber wenn Du Schritt für Schritt vorgehst, wirst Du merken, dass Du mit ein paar Funktionen aus readr, dplyr, readxl (und vielleicht writexl) schon 90 % Deiner Alltagsaufgaben erschlägst.

Der Schlüssel zum Erfolg ist, immer mal wieder neue Datensätze durchzuprobieren und Dir eine Art „Bibliothek“ an Code-Snippets (Codebeispielen) aufzubauen. Irgendwann kannst Du diese dann blind zusammenkopieren und hast ratzfatz Deine Daten geordnet.

In diesem Sinne: Viel Spaß beim Tüfteln und Ausprobieren! Und wenn Du mal nicht weiterkommst, gibt es immer die zahlreichen Online-Communities (Stack Overflow, RStudio Community), wo Dir geholfen wird.


Q&A (Fragen von Lernenden und Musterlösungen)

F: „Du, ich hab eine Tabelle, in der einige Zeilen doppelt vorkommen. Wie kann ich Duplikate entfernen oder zumindest erkennen?“
A (Musterlösung):

Du kannst mit distinct() aus dem dplyr-Paket arbeiten, das erkennt und entfernt Duplikate basierend auf allen oder ausgewählten Spalten. Zum Beispiel:

library(dplyr)
df_eindeutig <- distinct(dein_dataframe)

Das entfernt doppelte Zeilen. Willst Du es nur basierend auf einer Spalte machen, gibst Du sie als Parameter an.


F: „Ist es besser, NA-Werte zu löschen oder zu ersetzen?“
A (Musterlösung):

Kommt auf Deinen Use Case an. Wenn Du wenige NAs hast und sie wirklich zufällig verteilt sind, kannst Du oft einfach weglassen. Sind es aber viele und es gibt Muster, dann kann das Weglassen zu systematischen Verzerrungen führen. Dann muss man Imputationsmethoden anschauen.


F: „Welche Hilfe bekomme ich, wenn ich zum Beispiel read_csv nicht verstehe?“
A (Musterlösung):

Du kannst in R oder RStudio einfach ?read_csv eingeben oder help("read_csv"), um den Hilfetext zu lesen. Außerdem sind in vielen Paketen vignette() verfügbar, z. B. vignette("readr"), was Dir eine ausführliche Erklärung liefert.

Alles klar?

Ich hoffe, der Beitrag war für dich soweit verständlich. Wenn du weitere Fragen hast, nutze bitte hier die Möglichkeit, eine Frage an mich zu stellen!