
R ist eine funktionale und objektorientierte Programmiersprache für statistische Berechnungen und Graphiken. R ist weitestgehend zu der ursprünglich 1976 erschienen Sprache S kompatibel und kann als freie Implementierung derselbigen betrachtet werden. R wurde seit 1992 von den beiden Statistikern Ross Ihaka und Robert Gentleman an der Universität Auckland in Neuseeland entwickelt.
Der Name wurde als Anspielung auf die Sprache S und auf die Vornamen der beiden Erfinder gewählt. Seit 1995 steht R unter der GNU General Public License. 1997 entstand das Comprehensive R Archive Network (CRAN) als Anlehnung an das Comprehensive Perl Archive Network (CPAN).
Alleinstellungsmerkmale
R ist eine Sprache mit einer ganz klaren Zielgruppe: Im Gegensatz zu fast allen auf meinem Blog vorgestellten Sprachen handelt es sich in erster Linie nicht um eine Allzweck-Programmiersprache, sondern um eine Sprache für Anwender mit datenorientierten Problemen, wie Statistiker, Mathematiker und Datenwissenschaftler.
R bietet eingebaute Funktionen für Visualisierungen wie Plots, Graphen und Charts und Basisdatentypen wie Vektoren, Matrizen und Data Frames, was in vielen anderen Sprachen nur über Drittanbieterbibliotheken möglich ist, wie etwa pandas für Python.
R ist Open Source. Dies ist durchaus ein Alleinstellungsmerkmal, da die meisten Alternativen wie MATLAB, RapidMiner, SAS, SPSS, Tableau, TIBCO S-PLUS und Wolfram Mathematica unter proprietären Lizenzen stehen und die Nutzung kostenpflichtig ist.
Einsatzbereiche
R findet in der Industrie und Wissenschaft vielseitige Verwendung, unter anderem in der Finanzbranche, Genetik, Bioinformatik, Pharmaforschung, Sentimentanalyse, Geschäftsanalytik und explorativer Datenanalyse.
R wird unter anderem bei Facebook, Ford, Google, John Deere, Microsoft, Mozilla, dem National Weather Service, der New York Times und Thomas Cook eingesetzt.
Pros
R ist eine in seiner Domäne weitverbreitete Sprache, so dass man kaum darum herumkommt, sie zumindest rudimentär zu erlernen, auch wenn die eigene Wahl auf Alternativen wie Python und Julia oder proprietäre Software fällt. Mit über zehntausend Bibliotheken auf CRAN bietet R ein beachtliches Ökosystem, das neben diversen mathematischen und wissenschaftlichen Paketen auch Anbindungen an bekannte Technologien wie relationale Datenbanken, Spark, Kafka und Elasticsearch bietet.
Die eingebauten Visualisierungsmöglichkeiten und die REPL – R wird komplett interpretiert – machen den Einstieg und die Zusammenarbeit mit Kollegen sehr leicht, da keine weiteren Bibliotheken ausgewählt und installiert werden müssen, um Graphiken zu erstellen. Die eingebaute Paketverwaltung mit Anbindung an CRAN gestaltet die Installation von Bibliotheken sehr einfach.
R ist Open Source und für alle bekannten Plattformen verfügbar. Die grundsätzliche Syntax ist sehr einfach, so dass sich R auch als erste Programmiersprache gut eignet.
R unterstützt First-Class Functions und damit Closures. Mit Einschränkungen bzw. einem gewissen Aufwand ist der Aufruf von Code in anderen Sprachen wie C, C++ und Fortran aus R heraus möglich.
Cons
R unterstützt viele Konzepte nicht, die in den meisten Sprachen weitverbreitet sind. So gibt es keine Möglichkeit, die Sichtbarkeit von nicht-lokalen Variablen und Funktionen zu justieren oder Konstanten zu deklarieren.
R hat keinerlei eingebaute Security und ist damit für bestimmte Zwecke, etwa als Webserver-Backend, kaum geeignet. Hinsichtlich Geschwindigkeit und Speicherbedarf hat R starke Defizite gegenüber den meisten Allzweck-Programmiersprachen.
Man merkt R seine lange Historie und Kompatibilität mit S an. So unterstützt R beispielsweise vier Formen von Objektorientierung. Neben den Basistypen lassen sich via S3 mehrere Properties zu Objekten zusammenführen. S4 erweitert dieses Konzept, indem Properties typisiert werden und Vererbung möglich wird. In beiden Modellen sind Methoden allerdings an Funktionen geknüpft, und nicht an Objekte, was wiederum eine weitere Implementierung, die sogenannten Referenzklassen, adressieren. Bei diesem Ansatz sind Methoden nicht nur an Objekte gebunden, Properties können auch nachhaltig verändert werden, so dass diese Variante der aus Sprachen wie Java oder Python typischen Klassen am ehesten kommt.
Als Akzessor verwendet R nicht den in vielen Sprachen üblichen Punkt .
oder Pfeil ->
, sondern im Fall von S3 und Referenzklassen das Dollarzeichen $
und für S4 das At-Zeichen @
. Die allgemeine Syntax für die Deklaration von Klassen und Objekten, die nicht auf Schlüsselwörtern basiert, dürfte dabei für die meisten sehr unorthodox und wenig intuitiv wirken. Eine Klasse author
mit den Ausprägungen name
und age
und einer Funktion details
könnte in S3 so aussehen und verwendet werden:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | > author <- list (name = "Christian" , age = 36) > class (author) = "author" > author $name [1] "Christian" $age [1] 36 attr (, "class" ) [1] "author" > author$name [1] "Christian" > author$age [1] 36 > details <- function (object) { + UseMethod ( "details" ) + } > details.author <- function (object) { + cat ( "author: " , object$name, ", " , object$age, "\n" ) + } > details (author) author: Christian , 36 |
Der gleiche Code in S4 sieht wie folgt aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | > setClass ( "author" , + slots= list (name= "character" , age= "numeric" )) > author <- new ( "author" , name= "Christian" , age=36) > author An object of class "author" Slot "name" : [1] "Christian" Slot "age" : [1] 36 > author@name [1] "Christian" > author@age [1] 36 > setGeneric ( "details" , function (object) { + standardGeneric ( "details" ) + }) > setMethod ( "details" , "author" , function (object) { + cat ( "author: " , object@name, ", " , object@age, "\n" ) + }) > details (author) author: Christian , 36 |
Als Referenzklasse kann man das gleiche wie folgt schreiben:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | > author = setRefClass ( "author" , + fields= list (name= "character" , age= "numeric" ), + methods= list ( + details = function () { + cat ( "author: " , name, ", " , age, "\n" ) + })) > me = author$ new (name= "Christian" , age=36) > me$ details () author: Christian , 36 > me Reference class object of class "author" Field "name" : [1] "Christian" Field "age" : [1] 36 |
Zuweisungen in R können auf vielfältige Weise ausgedrückt werden, wobei teilweise subtile Unterschiede bestehen. Die folgenden Anweisungen haben alle zur Folge, dass x
den numerischen Wert 3
erhält:
1 2 3 4 | x <- 3 x = 3 3 -> x x <<- 3 |
R erlaubt sowohl Unterstriche als auch Punkte in Variablen- und Funktionsnamen. Z.B. ist Database.connect
ein valider Name. Für Anwender mit Vorerfahrung in gängigen objektorientierten Sprachen erweckt dies den Eindruck, dass es sich bei connect
um eine Methode der Klasse Database
handelt, tatsächlich ist dies aber der Name einer Top-Level-Funktion, da der Punkt an dieser Stelle keinerlei syntaktische Bedeutung hat. Dass verschiedene Bibliotheken unterschiedliche Namenskonventionen verwenden, etwa CamelCase, snake_case und die Verwendung des Punktes zur Trennung von Wörtern, lässt R-Code manchmal unnötig kompliziert und verwirrend erscheinen.
Zwar ist die Syntax allgemein nicht kompliziert, es existieren aber viele Stolpersteine, so liefert folgende Anweisung etwa den Wert 3
zurück:
1 | ifelse (3 == 4, c (1,2), c (3,4)) |
Warum ist dies so? Nun, ifelse()
nimmt eine Bedingung und zwei Werte entgegen und gibt je nachdem, ob die Bedingung wahr oder falsch ist den ersten oder zweiten Wert zurück, allerdings mit einer Besonderheit: Der zurückgegebene Wert muss dem in der Bedingung verwendeten entsprechen. 3
und 4
sind Literale, c(1, 2)
entgegen ist ein Vektor mit den Literalen 1
und 2
. Statt c(3, 4)
wird also der erste Wert aus dem Vektor zurückgegeben, was in dem Fall 3
ist. Statt ifelse(bedingung, wert1, wert2)
bietet es sich in dem Fall an, if (bedingung) wert1 else wert 2
zu schreiben.
Ein weiteres Beispiel: Um einen Vektor über die Funktion append(liste, vektor)
in eine Liste zu schreiben, muss dieser in einer Liste gekapselt werden, ansonsten wird nicht der eigentliche Vektor sondern dessen Inhalt als einzelne Positionen in die Liste geschrieben:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | > l = list () > append (l, c (1,2,3)) [[1]] [1] 1 [[2]] [1] 2 [[3]] [1] 3 > l = list () > append (l, list ( c (1,2,3))) [[1]] [1] 1 2 3 |
Als Fazit würde ich sagen, dass ich R als Allzweck-Programmiersprache nicht verwenden würde. Innerhalb seiner Domäne spielt es seine Vorteile aus und gerade wegen seiner Verbreitung sollte man in den jeweiligen Umfeldern mit R vertraut sein, aber für einen Software Engineer wie mich, der Geschäftsanwendungen entwickelt, gibt es keinen Grund, R einer anderen Sprache vorzuziehen.
Datenblatt
Name | R |
Webseite | https://www.r-project.org/ |
Erscheinungsjahr | 1993 |
Aktuellste Version (Stand 31. Dezember 2023) | Version 4.3.2 vom 31. Oktober 2023 |
Typisierung | dynamisch |
Paradigmen | funktional, objektorientiert |
Pros | Cons |
---|---|
einfacher Einstieg, REPL | hinsichtlich Performance und Speicherbedarf nur im Mittelfeld |
eingebaute Visualisierungsfunktionen | historische und eigenwillige Sprachkonstrukte, wenn man mehr machen möchte als die absoluten Grundlagen |
Open Source, plattformunabhängig | keine eingebaute Security |
großes Ökosystem und Community im Bereich Data Science, weit verbreitet in seiner Domäne | viele selbstverständliche Features wie etwa Konstanten sind nicht vorhanden |
virtuallet
virtuallet ist ein kleines Programm von mir, welches ich in diversen Programmiersprachen implementiert habe. Hier geht es direkt zum R-Code von virtuallet auf GitLab. Hier gibt es weitere Infos zu virtuallet.