Von SAS zu R und zurück: SAS-Daten nach R transferieren

SAS und R sind Themen, die dicht beieinanderliegen: Beides sind populäre Werkzeuge für Leute wie uns, die Probleme aus dem Umfeld von Statistik und Machine Learning auf mehr oder weniger großen Datenmengen lösen möchten. Trotz dieser scheinbaren Nähe gibt es wenig Berührungspunkte zwischen den beiden Communitys, und nur wenige arbeiten mit beiden Werkzeugen. Als passionierte Über-den-Tellerrand-Blicker finden wir das schade und möchten mit diesem Blogeintrag eine Miniserie starten, in der wir uns in loser Folge mit Themen beschäftigen, die beide Welten miteinander verbinden. Für diesen ersten Blogeintrag werden wir uns mit den Möglichkeiten beschäftigen, Daten zwischen den Systemen auszutauschen. Da es eine große Vielzahl an Wegen gibt, beschränken wir uns für diese Folge auf den Transfer von SAS zu R; der entgegengesetzte Weg folgt in einem späteren Eintrag.

Der Transfer von SAS zu R

Es gibt diverse Wege, SAS-Daten in ein R-System hineinzubekommen. Wir teilen sie in drei grobe Kategorien:
 

1. Die generischen Möglichkeiten

Mit "generisch" ist hier gemeint, dass diese Methoden generell für den Datentransfer zwischen allen möglichen unterschiedlichen Systemen taugen, nicht nur für R und SAS. Hier sind vor allem zwei Methoden zu nennen: der Transfer über CSV-Dateien und der gemeinsame Zugriff auf dieselbe relationale Datenbank.

Die erste Methode hat den Vorteil, dass sie wenig Spezial-Know-how benötigt. Die entsprechenden Befehle sind für die meisten Anwender gute alte Bekannte: PROC EXPORT auf SAS-Seite und read.csv in R bzw. der fread-Befehl aus dem data.table-Package als bessere Alternative nicht nur für große Datenmengen. Diejenigen, die diese Befehle schon öfter verwendet haben, wissen allerdings auch, dass sehr oft zeitaufwendige manuelle Feinarbeit notwendig ist, bis der Datenaustausch wirklich funktioniert. Das fängt bei der sinnvollen (und auf beiden Seiten übereinstimmenden) Wahl des Trennzeichens an. Insbesondere wenn zum Beispiel in Text-Mining-Anwendungen längere Freitexte ausgetauscht werden sollen, hört es damit aber noch lange nicht auf. Von der richtigen Wahl der Stringbegrenzer (die in Freitexten nicht vorkommen sollten) bis zur Behandlung von Problemen mit Encodings (insbesondere beim plattformübergreifenden Transfer von länderspezifischen Sonderzeichen) gibt es hier jede Menge Möglichkeiten, sich mit scheinbar kleinen Details lange zu beschäftigen. Eine unangenehme Option also für ungeduldige Menschen wie mich.

Der gemeinsame Zugriff auf dieselbe relationale Datenbank ist wesentlich angenehmer als der Transfer via CSV. Die Probleme mit Trennzeichen, Stringbegrenzern und teilweise auch Encodings fallen weg, und Datentypen können wesentlich leichter mitübertragen werden. Überdies bietet sich die Datenbank an, um die Daten nicht nur zu transferieren, sondern auch damit zu arbeiten. Es ist zudem leicht, beim Transfer gleich nur diejenigen Daten auszuwählen, die tatsächlich relevant sind. Allerdings ist diese Methode auch höchst voraussetzungsreich. Der Zugriff auf dieselbe Datenbank von beiden Systemen aus ist oft nicht gegeben. Er ist aber oft leichter herzustellen als eine direkte Verbindung zwischen R und SAS, wie sie die nächste Methode benötigt.
 

2. Die Methoden, die eine lokale SAS-Installation benutzen

Viele Methoden zum Einlesen von SAS-Daten in R setzen den Zugriff auf eine lokale SAS-Installation voraus. Weil diese Voraussetzung oft nicht erfüllt ist, gehen wir hier nicht näher auf diese Möglichkeiten ein.
 

3. Direkter Transfer von nativen SAS-Dateien ohne Rückgriff auf eine SAS-Installation

Das SAS7BDAT-Format ist das Standardformat auf SAS-Seite. Es existiert in verschiedenen Varianten; insbesondere gibt es die Möglichkeit, die Komprimierung ein- oder auszuschalten. Wenn man versucht, diese Dateien mit dem R-Package "foreign" zu lesen, erlebt man eine Überraschung. Es geht nämlich nicht. foreign ist zwar das erste Paket, das einem einfällt, wenn man fremde Dateiformate in R einlesen will, und es unterstützt auch SAS-Dateien. Aber leider beschränkt sich dieser Support auf ein uraltes Dateiformat (SAS XPORT), das in der SAS-Community kaum mehr benutzt wird. Das Format weist geradezu groteske Beschränkungen auf, vor allem dürfen Variablennamen nicht länger sein als acht Zeichen. Leider ist es das einzige SAS-Dateiformat, zu dem SAS eine Spezifikation offengelegt hat, was auch der Grund dafür sein dürfte, dass sich die Macher von foreign darauf beschränken. Sinnvoll nutzbar ist dieses Format nicht; es bietet gegenüber schlichten CSV-Dateien nur Nachteile. 

Glücklicherweise hat Matt Shotwell die Sisyphusaufgabe auf sich genommen, das Dateiformat SAS7BDAT zu analysieren. Er hat auf Basis der durch Reverse Engineering erworbenen Erkenntnisse ein R-Package gleichen Namens programmiert, das diese Dateien lesen kann (Schreiben ist nicht möglich). Leider kommt das Package nur mit der unkomprimierten Variante des Dateiformats zurecht. Für Alternativen, die auch komprimierte Dateien lesen können, siehe unten.

Das Einlesen einer SAS-Datei in R

Zum Glück ist es einfach, die Komprimierung beim Erzeugen der Datei abzuschalten: einfach im DATA-Step die Option "COMPRESS=NO" setzen. Allerdings schreiben sehr viele SAS-Systeme defaultmäßig die komprimierte Variante (das Defaultverhalten lässt sich mit OPTIONS konfigurieren). Das bedeutet, dass man in vielen Fällen nicht einfach eine SAS-Datei nehmen und in R einlesen kann. Vielmehr muss man eine in R lesbare Datei extra erzeugen, indem man die Kompression abschaltet. Dann funktioniert das Einlesen zuverlässig, wenn auch nicht übertrieben schnell.

Aufbauend auf der Arbeit von Matt Shotwell wurde später eine Java-Library entwickelt, die auch mit komprimierten Dateien zurechtkommt. Diese Java-Library hat Matt Shotwell wiederum in einem R-Package namens sas7bdat.parso zugreifbar gemacht. Dieses Package ist allerdings etwas schwieriger zu installieren (es benötigt rJava), und es ist nicht über CRAN verfügbar, sondern nur über GitHub. Ähnlich wie das SAS7BDAT-Package ist es eher langsam.

Der beste Weg ist also, wie so oft, von der genauen Situation abhängig. Persönlich würde ich den Weg über eine gemeinsam genutzte Datenbank präferieren, und wenn das nicht möglich ist, auf eines der beiden Packages von Matt Shotwell ausweichen. Wenn nichts anderes geht, würde ich mir schließlich mit CSV-Dateien behelfen. 

Views: 930
clear