R gehört zu den wichtigsten Programmiersprachen für Statistik, Datenanalyse, wissenschaftliches Arbeiten und Datenvisualisierung. Der Einstieg wirkt zunächst unkompliziert: Daten einlesen, Berechnungen durchführen und ein Diagramm erstellen. Bei größeren Projekten entstehen jedoch schnell typische Probleme.
Warum lässt sich ein Package nicht installieren? Weshalb erkennt R Zahlen als Text? Wie lassen sich fehlende Werte ignorieren? Wie kann ein Skript auf einem anderen Computer reproduzierbar ausgeführt werden?
Diese Sammlung zeigt praktische R-Tipps, die bei der täglichen Arbeit tatsächlich Zeit sparen. Die Beispiele richten sich an Einsteiger und fortgeschrittene Anwender und funktionieren überwiegend bereits mit den in R enthaltenen Basisfunktionen.
R ist eine Programmiersprache und Arbeitsumgebung für statistische Berechnungen, Datenverarbeitung und grafische Darstellungen. Die aktuelle R-Dokumentation beschreibt unter anderem Funktionen für Datenstrukturen, statistische Modelle, Programmierung und Grafiken.
1. Hilfe zu einer R-Funktion anzeigen
R verfügt über eine umfangreiche integrierte Dokumentation. Die Hilfeseite einer Funktion lässt sich mit einem Fragezeichen öffnen:
?mean
Alternativ funktioniert:
help(mean)
Ist der genaue Funktionsname unbekannt, kann nach einem Begriff gesucht werden:
??regression
Beispiele zu einer Funktion werden mit example() ausgeführt:
example(mean)
Die Argumente einer Funktion zeigt args():
args(read.csv)
Diese Befehle sind besonders nützlich, wenn unklar ist, welche Parameter eine Funktion akzeptiert oder welchen Rückgabewert sie erzeugt.
2. R-Version und Systeminformationen prüfen
Bei Installationsproblemen sollte zuerst geprüft werden, welche R-Version und welche Plattform tatsächlich verwendet werden:
R.version
Kompakter funktioniert:
R.version.string
Weitere Angaben zur laufenden Sitzung liefert:
sessionInfo()
Die Ausgabe enthält unter anderem:
- R-Version,
- Betriebssystem,
- Plattformarchitektur,
- Spracheinstellungen,
- geladene Packages,
- Package-Versionen.
Für Fehlermeldungen in Foren oder Supportanfragen sollte die Ausgabe von sessionInfo() mitgeliefert werden.
3. Ein R-Package installieren
Ein Package wird grundsätzlich nur einmal installiert:
install.packages("ggplot2")
Anschließend muss es in jeder neuen R-Sitzung geladen werden:
library(ggplot2)
Mehrere Packages können gleichzeitig installiert werden:
install.packages(
c(
"ggplot2",
"dplyr",
"readr"
)
)
install.packages() lädt Packages aus einem konfigurierten Repository und installiert standardmäßig auch notwendige Abhängigkeiten aus den Bereichen Depends, Imports und LinkingTo.
Installation und Laden nicht verwechseln
Diese beiden Befehle erfüllen unterschiedliche Aufgaben:
install.packages("dplyr")
library(dplyr)
install.packages() installiert das Package auf dem Computer. library() macht die Funktionen des bereits installierten Packages in der aktuellen Sitzung verfügbar.
Ein häufiger Fehler besteht darin, install.packages() am Anfang jedes Skripts auszuführen. Dadurch werden bei jeder Ausführung unnötige Prüfungen und möglicherweise Aktualisierungen ausgelöst.
4. Packages nur installieren, wenn sie fehlen
Mehrere benötigte Packages lassen sich automatisch prüfen und bei Bedarf installieren:
packages <- c(
"dplyr",
"ggplot2",
"readr"
)
missing_packages <- packages[
!vapply(
packages,
requireNamespace,
logical(1),
quietly = TRUE
)
]
if (length(missing_packages) > 0) {
install.packages(missing_packages)
}
Anschließend können die Packages geladen werden:
invisible(
lapply(
packages,
library,
character.only = TRUE
)
)
requireNamespace() ist für die reine Prüfung meist besser geeignet als library(), weil das Package dabei nicht automatisch an den Suchpfad angehängt wird.
5. Eine Funktion ohne library() verwenden
Eine einzelne Funktion kann direkt über den Package-Namen aufgerufen werden:
dplyr::filter(mtcars, cyl == 4)
Die Schreibweise besteht aus:
package::funktion
Das hat mehrere Vorteile:
- Der Ursprung einer Funktion ist sofort sichtbar.
- Namenskonflikte zwischen Packages werden vermieden.
- Das gesamte Package muss nicht an den Suchpfad angehängt werden.
- Skripte werden leichter nachvollziehbar.
Diese Schreibweise ist besonders bei häufig verwendeten Namen wie filter(), select() oder lag() sinnvoll.
6. Installierte Packages anzeigen
Alle installierten Packages können folgendermaßen angezeigt werden:
installed.packages()
Für eine übersichtlichere Liste der Package-Namen:
rownames(installed.packages())
Prüfen, ob ein bestimmtes Package installiert ist:
"ggplot2" %in% rownames(installed.packages())
Noch direkter:
requireNamespace("ggplot2", quietly = TRUE)
Das Ergebnis ist TRUE, wenn das Package verfügbar ist, andernfalls FALSE.
7. Packages aktualisieren
Verfügbare Aktualisierungen können interaktiv geprüft werden:
update.packages()
Ohne Rückfrage werden alle verfügbaren Updates installiert:
update.packages(
ask = FALSE,
checkBuilt = TRUE
)
Unter Windows können geladene Packages während der laufenden Sitzung gesperrt sein. Eine Aktualisierung sollte deshalb möglichst unmittelbar nach einem Neustart von R erfolgen.
8. Library-Pfade anzeigen und ändern
R sucht installierte Packages in sogenannten Library-Verzeichnissen. Die aktuell verwendeten Verzeichnisse zeigt:
.libPaths()
Ein zusätzliches Verzeichnis kann an den Anfang des Suchpfades gesetzt werden:
custom_library <- "D:/R/library"
dir.create(
custom_library,
recursive = TRUE,
showWarnings = FALSE
)
.libPaths(
c(
custom_library,
.libPaths()
)
)
.libPaths() dient zum Anzeigen und Festlegen jener Verzeichnisse, in denen R nach Packages sucht.
Auf Windows sollten in R entweder Schrägstriche oder doppelte Backslashes verwendet werden:
"D:/R/library"
oder:
"D:\\R\\library"
Diese Schreibweise ist falsch:
"D:\R\library"
Einzelne Backslashes können als Beginn einer Escape-Sequenz interpretiert werden.
9. Portable R-Versionen richtig konfigurieren
Bei einer portablen R-Installation muss der Library-Pfad auf das vorhandene Package-Verzeichnis zeigen:
portable_library <- file.path(
getwd(),
"library"
)
dir.create(
portable_library,
recursive = TRUE,
showWarnings = FALSE
)
.libPaths(
c(
portable_library,
.libPaths()
)
)
Der frühere Tipp, bei Problemen die ausführbare Datei im Verzeichnis i386 zu starten, ist für aktuelle R-Versionen nicht mehr geeignet. Seit R 4.2.0 werden für Windows ausschließlich 64-Bit-Builds angeboten.
Bei einer portablen Installation sollte deshalb geprüft werden:
R.version$arch
R.home()
.libPaths()
10. Dateipfade plattformunabhängig erstellen
Dateipfade sollten nicht manuell zusammengesetzt werden:
pfad <- "daten/2026/umsatz.csv"
Robuster ist file.path():
pfad <- file.path(
"daten",
"2026",
"umsatz.csv"
)
R verwendet dadurch automatisch das für das Betriebssystem passende Trennzeichen.
Prüfen, ob eine Datei existiert:
file.exists(pfad)
Prüfen, ob ein Verzeichnis existiert:
dir.exists("daten")
Ein Verzeichnis bei Bedarf erstellen:
dir.create(
file.path("daten", "2026"),
recursive = TRUE,
showWarnings = FALSE
)
11. Arbeitsverzeichnis anzeigen
Das aktuelle Arbeitsverzeichnis wird mit folgendem Befehl ausgegeben:
getwd()
Es lässt sich manuell ändern:
setwd("D:/Projekte/meine-analyse")
Dauerhaft mit absoluten Pfaden zu arbeiten, ist allerdings fehleranfällig. Besser ist ein projektbasierter Aufbau, bei dem alle Pfade relativ zum Projektverzeichnis angegeben werden:
daten <- read.csv2(
file.path(
"daten",
"umsatz.csv"
)
)
Damit kann das gesamte Projekt leichter auf einen anderen Computer verschoben werden.
12. CSV-Dateien richtig einlesen
Für CSV-Dateien mit Komma als Spaltentrennzeichen und Punkt als Dezimalzeichen:
daten <- read.csv(
"daten.csv"
)
Für die im deutschsprachigen Raum häufige Kombination aus Semikolon als Spaltentrennzeichen und Komma als Dezimalzeichen:
daten <- read.csv2(
"daten.csv"
)
Die Unterschiede liegen in den Standardwerten:
read.csv(
file,
sep = ",",
dec = "."
)
read.csv2(
file,
sep = ";",
dec = ","
)
read.csv() und read.csv2() sind Varianten von read.table() mit unterschiedlichen Voreinstellungen für Feld- und Dezimaltrennzeichen.
Bei Umlauten oder Sonderzeichen kann die Kodierung explizit angegeben werden:
daten <- read.csv2(
"daten.csv",
fileEncoding = "UTF-8"
)
Für ältere Windows-Dateien kann beispielsweise notwendig sein:
daten <- read.csv2(
"daten.csv",
fileEncoding = "Windows-1252"
)
13. Daten nach dem Import kontrollieren
Nach jedem Import sollte geprüft werden, ob die Daten korrekt erkannt wurden.
Die ersten Zeilen anzeigen:
head(daten)
Die letzten Zeilen anzeigen:
tail(daten)
Struktur und Datentypen prüfen:
str(daten)
Zusammenfassende Statistiken anzeigen:
summary(daten)
Spaltennamen ausgeben:
names(daten)
Anzahl der Zeilen und Spalten:
dim(daten)
Nur die Zeilenanzahl:
nrow(daten)
Nur die Spaltenanzahl:
ncol(daten)
Ein erfolgreicher Import bedeutet nicht automatisch, dass alle Spalten korrekt interpretiert wurden. Zahlen können beispielsweise als Text eingelesen worden sein.
14. Datentypen prüfen und umwandeln
Den Datentyp eines Objekts zeigt:
class(daten$umsatz)
Zusätzliche Informationen liefern:
typeof(daten$umsatz)
mode(daten$umsatz)
Eine Textspalte in Zahlen umwandeln:
daten$umsatz <- as.numeric(
daten$umsatz
)
Enthält die Spalte Dezimalkommas, müssen diese vorher ersetzt werden:
daten$umsatz <- as.numeric(
sub(
",",
".",
daten$umsatz,
fixed = TRUE
)
)
Datumswerte lassen sich folgendermaßen umwandeln:
daten$datum <- as.Date(
daten$datum,
format = "%d.%m.%Y"
)
Häufige Datumsformate:
| Format | Bedeutung |
|---|---|
%d | Tag |
%m | Monat als Zahl |
%Y | vierstelliges Jahr |
%y | zweistelliges Jahr |
%H | Stunde |
%M | Minute |
%S | Sekunde |
Beispiel für Datum und Uhrzeit:
zeitpunkt <- as.POSIXct(
"30.07.2026 14:35:00",
format = "%d.%m.%Y %H:%M:%S",
tz = "Europe/Vienna"
)
15. Fehlende Werte erkennen
Fehlende Werte werden in R normalerweise als NA dargestellt.
Prüfen, welche Werte fehlen:
is.na(daten$umsatz)
Anzahl der fehlenden Werte:
sum(
is.na(daten$umsatz)
)
Prüfen, ob überhaupt ein Wert fehlt:
anyNA(daten)
Nur vollständige Zeilen auswählen:
vollstaendig <- daten[
complete.cases(daten),
]
Zeilen entfernen, die irgendwo einen fehlenden Wert enthalten:
daten_ohne_na <- na.omit(daten)
na.omit() sollte nicht unkritisch auf umfangreiche Datensätze angewendet werden. Eine Zeile wird bereits entfernt, wenn nur eine einzige der enthaltenen Spalten fehlt.
16. Berechnungen trotz fehlender Werte durchführen
Viele statistische Funktionen geben NA zurück, sobald der Eingabevektor mindestens einen fehlenden Wert enthält:
mean(
c(10, 20, NA)
)
Ergebnis:
NA
Fehlende Werte können bei der Berechnung ignoriert werden:
mean(
c(10, 20, NA),
na.rm = TRUE
)
Weitere Beispiele:
sum(
daten$umsatz,
na.rm = TRUE
)
min(
daten$umsatz,
na.rm = TRUE
)
max(
daten$umsatz,
na.rm = TRUE
)
median(
daten$umsatz,
na.rm = TRUE
)
17. Zeilen nach Bedingungen filtern
Nur Fahrzeuge mit mehr als 100 PS:
auswahl <- mtcars[
mtcars$hp > 100,
]
Mehrere Bedingungen mit & verbinden:
auswahl <- mtcars[
mtcars$hp > 100 &
mtcars$cyl == 6,
]
Mindestens eine von mehreren Bedingungen mit |:
auswahl <- mtcars[
mtcars$cyl == 4 |
mtcars$cyl == 6,
]
Werte aus einer Liste auswählen:
auswahl <- mtcars[
mtcars$cyl %in% c(4, 6),
]
Fehlende Werte explizit ausschließen:
auswahl <- daten[
!is.na(daten$umsatz) &
daten$umsatz > 1000,
]
18. Spalten auswählen
Eine einzelne Spalte als Vektor:
mtcars$mpg
Alternativ:
mtcars[["mpg"]]
Mehrere Spalten als Data Frame:
auswahl <- mtcars[
c(
"mpg",
"cyl",
"hp"
)
]
Spalten über ihre Position auswählen:
auswahl <- mtcars[
,
1:3
]
Spalten ausschließen:
auswahl <- mtcars[
,
!names(mtcars) %in% c(
"vs",
"am"
)
]
Für stabilen Code sind Spaltennamen meistens besser als Positionsnummern. Die Reihenfolge der Spalten kann sich ändern, ihre Bedeutung sollte hingegen gleich bleiben.
19. Daten sortieren
Einen Vektor aufsteigend sortieren:
sort(
mtcars$mpg
)
Absteigend sortieren:
sort(
mtcars$mpg,
decreasing = TRUE
)
Einen vollständigen Data Frame nach einer Spalte sortieren:
sortiert <- mtcars[
order(mtcars$mpg),
]
Absteigend:
sortiert <- mtcars[
order(
mtcars$mpg,
decreasing = TRUE
),
]
Nach mehreren Spalten sortieren:
sortiert <- mtcars[
order(
mtcars$cyl,
-mtcars$hp
),
]
Das Ergebnis wird zuerst nach cyl aufsteigend und innerhalb jeder Gruppe nach hp absteigend sortiert.
20. Doppelte Werte finden und entfernen
Prüfen, welche Werte doppelt vorkommen:
duplicated(
daten$kunden_id
)
Alle mehrfach vorkommenden Zeilen anzeigen:
daten[
duplicated(daten$kunden_id) |
duplicated(
daten$kunden_id,
fromLast = TRUE
),
]
Doppelte Datensätze entfernen:
daten_eindeutig <- daten[
!duplicated(daten),
]
Eindeutige Werte einer Spalte ausgeben:
unique(
daten$kunden_id
)
Anzahl unterschiedlicher Werte:
length(
unique(daten$kunden_id)
)
21. Häufigkeiten und Kreuztabellen erstellen
Häufigkeit einzelner Werte:
table(
mtcars$cyl
)
Prozentuale Verteilung:
prop.table(
table(mtcars$cyl)
)
Kreuztabelle aus zwei Variablen:
table(
mtcars$cyl,
mtcars$am
)
Zeilenweise Prozentwerte:
prop.table(
table(
mtcars$cyl,
mtcars$am
),
margin = 1
)
Spaltenweise Prozentwerte:
prop.table(
table(
mtcars$cyl,
mtcars$am
),
margin = 2
)
22. Daten nach Gruppen auswerten
Der durchschnittliche Verbrauch nach Zylinderzahl kann mit aggregate() berechnet werden:
aggregate(
mpg ~ cyl,
data = mtcars,
FUN = mean
)
Mehrere Kennzahlen gleichzeitig:
aggregate(
cbind(mpg, hp) ~ cyl,
data = mtcars,
FUN = mean
)
Fehlende Werte ignorieren:
aggregate(
umsatz ~ region,
data = daten,
FUN = mean,
na.rm = TRUE
)
Für einfache gruppierte Auswertungen ist aggregate() eine leistungsfähige Basisfunktion, die kein zusätzliches Package benötigt.
23. Die native Pipe verwenden
Lange, verschachtelte Funktionsaufrufe sind oft schwer lesbar:
nrow(
subset(
mtcars,
cyl == 4
)
)
Mit der nativen R-Pipe wird daraus:
mtcars |>
subset(cyl == 4) |>
nrow()
Das Ergebnis der linken Seite wird standardmäßig als erstes Argument an die nächste Funktion übergeben. Die native Pipe |> ist seit R 4.1.0 Bestandteil der Sprache.
Ein weiteres Beispiel:
mtcars |>
subset(cyl == 6) |>
transform(
verbrauch_l_100km = 235.215 / mpg
) |>
head()
Die einzelnen Verarbeitungsschritte werden dadurch von oben nach unten lesbar.
24. Schleifen durch Vektorisierung ersetzen
Eine unnötige Schleife:
werte <- 1:100
ergebnis <- numeric(
length(werte)
)
for (i in seq_along(werte)) {
ergebnis[i] <- werte[i] * 2
}
In R genügt:
ergebnis <- werte * 2
Viele mathematische Operationen werden automatisch auf alle Elemente eines Vektors angewendet:
werte + 10
werte^2
sqrt(werte)
log(werte)
round(werte, 2)
Vektorisierter Code ist häufig kürzer, leichter lesbar und schneller.
Schleifen sind dennoch nicht grundsätzlich falsch. Wenn eine Schleife erforderlich ist, sollte der Ergebnisvektor vorher mit der benötigten Größe angelegt werden.
25. apply(), lapply() und sapply() verwenden
Spaltensummen einer Matrix:
matrix_daten <- as.matrix(
mtcars[
c(
"mpg",
"hp",
"wt"
)
]
)
apply(
matrix_daten,
2,
sum
)
Die Zahl 2 bedeutet, dass die Funktion spaltenweise angewendet wird. Mit 1 erfolgt die Berechnung zeilenweise.
Eine Funktion auf mehrere Listenelemente anwenden:
lapply(
mtcars,
class
)
sapply() versucht, das Ergebnis zu vereinfachen:
sapply(
mtcars,
class
)
Für vorhersehbaren Programmcode ist vapply() häufig sicherer:
vapply(
mtcars,
class,
character(1)
)
Bei vapply() wird der erwartete Rückgabetyp ausdrücklich angegeben.
26. Eigene Funktionen erstellen
Wiederkehrende Berechnungen sollten in eine Funktion ausgelagert werden:
berechne_netto <- function(
brutto,
steuersatz = 0.20
) {
brutto / (
1 + steuersatz
)
}
Aufruf:
berechne_netto(120)
Mit anderem Steuersatz:
berechne_netto(
120,
steuersatz = 0.10
)
Eingaben können geprüft werden:
berechne_netto <- function(
brutto,
steuersatz = 0.20
) {
if (!is.numeric(brutto)) {
stop(
"brutto muss numerisch sein."
)
}
if (
steuersatz < 0 ||
steuersatz >= 1
) {
stop(
"steuersatz muss zwischen 0 und 1 liegen."
)
}
brutto / (
1 + steuersatz
)
}
Eine Funktion sollte eine klar abgegrenzte Aufgabe erfüllen und möglichst keine versteckten Änderungen an globalen Variablen durchführen.
27. Farben für Diagramme automatisch erzeugen
Für unterschiedliche Farben wird kein zusätzliches Package benötigt.
Beispiel mit Regenbogenfarben:
anzahl <- 6
farben <- rainbow(anzahl)
barplot(
1:anzahl,
col = farben
)
Für besser abgestimmte Farbpaletten eignet sich hcl.colors():
farben <- hcl.colors(
6,
palette = "Dark 3"
)
barplot(
1:6,
col = farben
)
Verfügbare Paletten anzeigen:
hcl.pals()
Mehrere Linien automatisch einfärben:
matplot(
1:10,
matrix(
rnorm(50),
ncol = 5
),
type = "l",
lty = 1,
col = hcl.colors(
5,
"Dark 3"
)
)
Die Anzahl der Farben sollte zur Zahl der dargestellten Gruppen passen.
28. Diagramme als Datei speichern
Ein Diagramm kann direkt als PNG-Datei gespeichert werden:
png(
filename = "diagramm.png",
width = 1600,
height = 900,
res = 150
)
plot(
mtcars$wt,
mtcars$mpg,
xlab = "Gewicht",
ylab = "Meilen pro Gallone",
main = "Verbrauch nach Fahrzeuggewicht"
)
dev.off()
Als PDF:
pdf(
"diagramm.pdf",
width = 10,
height = 6
)
plot(
mtcars$wt,
mtcars$mpg
)
dev.off()
dev.off() beendet das Grafikgerät und schreibt die Datei vollständig auf den Datenträger. Wird dieser Befehl vergessen, kann die Ausgabedatei leer oder unvollständig bleiben.
29. Zufallszahlen reproduzierbar erzeugen
Zufallsbasierte Analysen sollten einen festen Startwert verwenden:
set.seed(2026)
werte <- rnorm(10)
Wird derselbe Seed vor der Berechnung erneut gesetzt, entstehen dieselben Zufallszahlen:
set.seed(2026)
rnorm(10)
Das ist relevant für:
- Stichproben,
- Simulationen,
- Train-Test-Aufteilungen,
- Random-Forest-Modelle,
- Bootstrap-Verfahren,
- zufällige Initialisierungen.
Der Seed sollte im Skript unmittelbar vor dem zufallsabhängigen Verarbeitungsschritt stehen.
30. Fehler und Warnungen gezielt untersuchen
Nach einem Fehler zeigt traceback() die zuletzt durchlaufenen Funktionsaufrufe:
traceback()
Warnungen der aktuellen Sitzung anzeigen:
warnings()
Eine Bedingung ausdrücklich prüfen:
if (!file.exists("daten.csv")) {
stop(
"Die Datei daten.csv wurde nicht gefunden."
)
}
Warnung erzeugen:
if (anyNA(daten)) {
warning(
"Der Datensatz enthält fehlende Werte."
)
}
Fehler kontrolliert behandeln:
ergebnis <- tryCatch(
{
read.csv2("daten.csv")
},
error = function(e) {
message(
"Import fehlgeschlagen: ",
conditionMessage(e)
)
NULL
}
)
tryCatch() ist sinnvoll, wenn ein Fehler behandelt werden kann, ohne das gesamte Skript unkontrolliert abzubrechen.
31. Objekte aus dem Arbeitsspeicher entfernen
Ein einzelnes Objekt löschen:
rm(daten)
Mehrere Objekte löschen:
rm(
daten,
ergebnis,
auswahl
)
Alle Objekte aus der globalen Umgebung entfernen:
rm(
list = ls()
)
Speicherbereinigung anfordern:
gc()
rm(list = ls()) sollte nicht automatisch am Anfang jedes Skripts stehen. Besser ist eine neue, saubere R-Sitzung oder ein eigenständiges Projekt. Das verhindert, dass wichtige Objekte unbemerkt gelöscht werden.
32. Ergebnisse speichern und wieder laden
Ein einzelnes R-Objekt speichern:
saveRDS(
daten,
"daten.rds"
)
Das Objekt wieder einlesen:
daten_neu <- readRDS(
"daten.rds"
)
Mehrere Objekte gemeinsam speichern:
save(
daten,
modell,
file = "analyse.RData"
)
Wieder laden:
load(
"analyse.RData"
)
Für einzelne Objekte sind saveRDS() und readRDS() meist übersichtlicher, weil der Name des geladenen Objekts frei gewählt werden kann.
33. Reproduzierbare Projekte mit renv
Bei langfristigen Projekten kann eine spätere Package-Aktualisierung bestehende Skripte verändern oder beschädigen. Das Package renv legt deshalb für jedes Projekt eine eigene Package-Bibliothek und eine Lockdatei an.
Installation:
install.packages("renv")
Projekt initialisieren:
renv::init()
Aktuellen Package-Stand speichern:
renv::snapshot()
Gespeicherten Zustand auf einem anderen System wiederherstellen:
renv::restore()
Die Datei renv.lock enthält die für die Wiederherstellung notwendigen Informationen zu den verwendeten Package-Versionen. Unterschiedliche Projekte können dadurch voneinander isolierte Package-Umgebungen verwenden.
34. Java-Probleme in R richtig behandeln
R selbst benötigt für den normalen Betrieb kein Java. Java ist nur erforderlich, wenn ein verwendetes Package darauf angewiesen ist, beispielsweise rJava oder ein darauf aufbauendes Package.
Aktuelle Einstellung prüfen:
Sys.getenv(
"JAVA_HOME"
)
Java-Version außerhalb von R prüfen:
java -version
Architektur von R anzeigen:
R.version$arch
Bei einem aktuellen 64-Bit-R muss auch eine kompatible 64-Bit-Java-Installation verwendet werden.
JAVA_HOME kann für die laufende Sitzung gesetzt werden:
Sys.setenv(
JAVA_HOME = "C:/Program Files/Java/jdk-XX"
)
XX muss durch die tatsächlich installierte Version ersetzt werden. Ein fest eingetragener alter Pfad wie jre1.8.0_45 sollte nicht übernommen werden.
Danach kann getestet werden:
library(rJava)
.jinit()
Besteht das Problem nach einer Änderung weiterhin, müssen R oder RStudio vollständig beendet und neu gestartet werden.
35. Ein minimales reproduzierbares Beispiel erstellen
Bei einer Supportanfrage sollte das Problem mit möglichst wenig Code reproduzierbar sein.
Ein kleines Beispieldataset kann direkt im Skript erzeugt werden:
daten <- data.frame(
kunde = c(
"A",
"B",
"C"
),
umsatz = c(
100,
NA,
250
)
)
Anschließend folgt nur jener Code, der den Fehler auslöst:
mean(
daten$umsatz
)
Ein gutes reproduzierbares Beispiel enthält:
- kleine Beispieldaten,
- den tatsächlich ausgeführten Code,
- die vollständige Fehlermeldung,
- das erwartete Ergebnis,
- die Ausgabe von
sessionInfo().
Nicht notwendig sind vertrauliche Echtdaten, Screenshots unvollständiger Fehlermeldungen oder Hunderte Zeilen irrelevanter Programmcode.
Häufige R-Fehler und ihre Ursachen
„could not find function“
Beispiel:
could not find function "filter"
Mögliche Ursache: Das zugehörige Package wurde nicht geladen.
Lösung:
library(dplyr)
oder:
dplyr::filter(
mtcars,
cyl == 4
)
„there is no package called …“
Das Package ist in der verwendeten Library nicht installiert:
install.packages(
"PackageName"
)
Anschließend:
library(PackageName)
Zusätzlich sollten die aktiven Library-Pfade geprüft werden:
.libPaths()
„object not found“
Beispiel:
object 'umsatz' not found
Mögliche Ursachen:
- Schreibfehler,
- falsche Groß- und Kleinschreibung,
- Objekt wurde noch nicht erstellt,
- Spalte gehört zu einem Data Frame,
- vorheriger Programmteil ist mit einem Fehler abgebrochen.
R unterscheidet Groß- und Kleinschreibung:
Umsatz
umsatz
Das sind zwei unterschiedliche Objekte.
„NAs introduced by coercion“
Die Umwandlung in einen numerischen Datentyp ist fehlgeschlagen:
as.numeric(
c(
"10",
"20",
"unbekannt"
)
)
Der nicht numerische Wert wird zu NA.
Problematische Werte lassen sich finden:
werte <- c(
"10",
"20",
"unbekannt"
)
werte[
is.na(
suppressWarnings(
as.numeric(werte)
)
)
]
„cannot open the connection“
R kann eine Datei oder Verbindung nicht öffnen.
Zu prüfen sind:
getwd()
file.exists("daten.csv")
list.files()
Bei einem absoluten Pfad:
file.exists(
"D:/Projekte/daten.csv"
)
Häufige Ursachen sind ein falsches Arbeitsverzeichnis, ein Tippfehler, fehlende Berechtigungen oder eine durch ein anderes Programm gesperrte Datei.
„unexpected symbol“ oder „unexpected end of input“
Dabei handelt es sich meistens um einen Syntaxfehler:
- fehlende schließende Klammer,
- fehlendes Komma,
- nicht geschlossenes Anführungszeichen,
- zusätzliche Zeichen,
- unvollständiger Ausdruck.
Fehlerhaft:
mean(
c(1, 2, 3)
Korrekt:
mean(
c(1, 2, 3)
)
Empfohlene Struktur für ein R-Projekt
Ein übersichtliches Projekt könnte folgendermaßen aufgebaut sein:
mein-projekt/
├── daten/
│ ├── roh/
│ └── verarbeitet/
├── skripte/
│ ├── 01_import.R
│ ├── 02_bereinigung.R
│ ├── 03_analyse.R
│ └── 04_diagramme.R
├── ausgabe/
│ ├── tabellen/
│ └── diagramme/
├── renv/
├── renv.lock
└── README.md
Die einzelnen Skripte sollten eine klare Aufgabe besitzen:
01_import.R: Daten einlesen,02_bereinigung.R: Datentypen und Fehler korrigieren,03_analyse.R: Berechnungen und Modelle,04_diagramme.R: grafische Ausgaben.
Dadurch lassen sich Fehler leichter eingrenzen und einzelne Verarbeitungsschritte gezielt erneut ausführen.
Zehn grundlegende Regeln für besseren R-Code
- Packages nicht bei jeder Ausführung neu installieren.
- Nach jedem Datenimport
str()undsummary()ausführen. - Relative Projektpfade statt persönlicher absoluter Pfade verwenden.
- Wiederkehrende Abläufe in Funktionen auslagern.
- Fehlende Werte bewusst behandeln.
- Aussagekräftige Objekt- und Spaltennamen verwenden.
- Zufallsprozesse mit
set.seed()reproduzierbar machen. - Package-Versionen bei wichtigen Projekten mit
renvsichern. - Fehler mit kleinen reproduzierbaren Beispielen untersuchen.
- Zwischenschritte kontrollieren, statt ein vollständiges Skript blind auszuführen.
Fazit: Mit wenigen R-Tipps schneller und zuverlässiger arbeiten
Effizientes Arbeiten mit R hängt weniger vom Auswendiglernen möglichst vieler Befehle als von einer sauberen Arbeitsweise ab.
Besonders wichtig sind:
- Packages kontrolliert installieren und laden,
- Daten unmittelbar nach dem Import prüfen,
- fehlende Werte ausdrücklich behandeln,
- Pfade portabel aufbauen,
- wiederkehrenden Code in Funktionen auslagern,
- Projekte reproduzierbar strukturieren,
- Fehlermeldungen systematisch untersuchen.
Viele alltägliche Aufgaben lassen sich bereits mit Basis-R lösen. Zusätzliche Packages sind vor allem dann sinnvoll, wenn sie einen konkreten Vorteil bei Datenverarbeitung, Visualisierung oder Reproduzierbarkeit bieten. Ein klar aufgebautes Skript mit nachvollziehbaren Verarbeitungsschritten ist langfristig wertvoller als eine Sammlung unstrukturierter Einzelbefehle.