Excel-Datensätze in R laden: Geschwindigkeits-Test verschiedener R-Pakete

Welche Möglichkeiten gibt es, große Excel-Datensätze schnell in R zu laden? Wir verwenden einen Beispiel-Datensatz mit 29 Variablen (Spalten) und 2.000 bzw. 10.000 Zeilen (Fällen).

Das R-Paket gdata

Als ich zum ersten Mal Exceldaten in R laden wollte, stieß ich auf das gdata-Paket. Es bietet zahlreiche Erweiterungen der R-Basisfunktionalität. Zum Import von Exceldaten wandelt es die Exceldatei zunächst per Perl-Skript in eine csv-Datei um und lädt diese dann. Dadurch ist es extrem ineffizient für den Import großer Datenmengen.

Hier ein Codeschnipsel. Zur Zeitmessung verwende ich die Funktion Sys.time(), die die aktuelle Systemzeit ausgibt. Sie wird vor und nach dem Ladevorgang erfasst, die Differenz ist der Zeitbedarf des Ladevorgangs.

require(gdata)
 Start <- Sys.time()
 gdata_xlsx <- read.xls("2008_d.xlsx")
 Ende <- Sys.time()
 Zeit_gdata <- Ende - Start
 cat("n Laufzeit gdata, 2.000 Zeilen: ", Zeit_gdata, "Sekunden") 

Die Laufzeit hängt natürlich vom System ab und kann je nach Auslastung des Rechners und Hintergrundprozessen schwanken. Für gdata komme ich auf meinem System auf Zeiten von etwas mehr als 10 Sekunden für die Datei mit 2.000 Zeilen. Für größere Excel-Dateien rate ich dringend von gdata ab!

Das R-Paket XLConnect

Wie sieht es mit XLConnect aus? Dieses Paket baut gleichsam eine Brücke zu Excel – man kann damit von R aus Excelblätter anlegen, dort Daten eintragen, Arbeitsmappen anlegen und speichern etc. Dazu greift XLConnect auf Java zurück.

require(XLConnect)

# Speicherplatz für Java erhöhen
options(java.parameters = "-Xmx1g" )

Start <- Sys.time()
wb <- loadWorkbook("2008_d.xlsx")
XLConnect_xlsx <- readWorksheet(wb, sheet = "2008")
Ende <- Sys.time()
Zeit_XLConnect <- Ende - Start
cat("n Laufzeit XLConnect, 2.000 Zeilen: ", Zeit_XLConnect, "Sekunden")

Für die Datei mit 2.000 Zeilen braucht mein System nun schon weniger als eine Sekunde – meist um die 0,4 Sekunden, manchmal bis zu 0,8 (im Video waren es 1,7). XLConnect ist ungefähr um den Faktor 6 bis 20 schneller als gdata.

Die Ladezeit für die Datei mit 10.000 Zeilen betrug um die 6 Sekunden – allerdings kommt Java bei größeren Dateien an Speichergrenzen. Typische Meldung:

Error: OutOfMemoryError (Java): Java heap space



Das R-Paket xlsx

require(xlsx)
# Wir verwenden nur die schnellere Funktion read.xlsx2, nicht read.xlsx (viel langsamer)

Start <- Sys.time()
xlsx_xlsx <- read.xlsx2("2008_c.xlsx", 1)
Ende <- Sys.time()
Zeit_xlsx <- Ende - Start
cat("n Laufzeit xlsx, 10.000 Zeilen: ", Zeit_xlsx, "Sekunden")

xlsx greift ebenfalls auf Java zurück und ermöglicht ebenfalls weitgehende Kontrolle über Excel-Dateien aus R heraus. Die Laufzeit für die Datei mit 10.000 Zeilen zwischen 3 Sekunden und 15 Sekunden. Die kleinere Datei mit 2.000 Zeilen wurde durchgängig in weniger als einer Sekunde geladen, um die 0,3 Sekunden.

Das R-Paket openxlsx

detach(package:xlsx)
require(openxlsx)

Start <- Sys.time()
openxlsx_xlsx <- read.xlsx("2008_c.xlsx")
Ende <- Sys.time()
Zeit_openxlsx <- Ende - Start
cat("n Laufzeit openxlsx, 10.000 Zeilen: ", Zeit_openxlsx, "Sekunden")

Da xlsx und openxlsx zum Teil gleiche Befehle verwenden, habe ich zuerst das xlsx-Paket deaktiviert. Das openxlsx-Paket ist mit Abstand das schnellste der bisher getesteten: Es lädt die 10.000-Zeilen-Datei konstant in weniger als einer Sekunde (bei mir zwischen 0,65 und 0,9 Sekunden).

Das readxl-Paket von Hadley Wickham

require(readxl)

Start <- Sys.time()
readxl_xlsx <- read_excel("2008_c.xlsx")
Ende <- Sys.time()
Zeit_readxl <- Ende - Start
cat("n Laufzeit readxl, 10.000 Zeilen: ", Zeit_readxl, "Sekunden")

as.numeric(Zeit_openxlsx) / as.numeric(Zeit_readxl)

readxl ist noch schneller: um 0,3 Sekunden für die größere Datei mit 10.000 Zeilen, und damit mehr als doppelt so schnell wie das zweitschnellste Paket openxlsx. Fürs Excel-Format ist Hadley Wickhams Paket das schnellste, das ich kenne.

Ich habe noch eine größere Datei mit 1 Million Zeilen (und ebenfalls 29 Variablen) vorbereitet. Diese konnte ich auch mit readxl nicht in vertretbarer Zeit laden (Abbruch nach 20 Minuten). Spätestens bei solchen Datenmengen ist es schlicht nicht ratsam, mit dem Excelformat zu arbeiten.

Große Datenmengen: Welches Paket gewinnt beim .csv-Format?

Erster Kandidat: Die Basisfunktion read.csv

Die Basisfunktion read.csv beruht auf read.table, ist aber anwenderfreundlicher, da einige Einstellungen bereits auf das .csv-Format abzielen.

Start <- Sys.time()
daten <- read.csv("2008b.csv")
Ende <- Sys.time()
Zeit_read.csv <- Ende - Start
cat("n Laufzeit read.csv, 1.000.000 Zeilen: ", Zeit_read.csv, "Sekunden")

Die Datei mit einer Million Zeilen konnte ich damit in 12 bis 13 Sekunden laden.

Hadley Wickhams readr-Paket

require(readr)
Start <- Sys.time()
daten <- read_csv("2008b.csv")
Ende <- Sys.time()
Zeit_readr <- Ende - Start
cat("n Laufzeit readr, 1.000.000 Zeilen: ", Zeit_readr, "Sekunden")

Beim readr-Paket muss man sich an den Unterstrich (read_csv) gewöhnen. Es ist ca. 5 Mal so schnell wie read.csv und schaffte die Datei mit einer Million Zeilen in etwas mehr als zwei Sekunden. Nettes Feature: Ein (wenn auch simpler) Fortschrittsbalken.

data.table von Matt Dowle und Arun Srinivasan

Das data.table-Paket erfreut sich zunehmender Beliebtheit, vor allem im Hinblick auf die Verarbeitung großer Datensätze. Um es anzuwenden, muss man gegenüber den herkömmlichen R-Funktionen etwas umdenken, da es eine andere Syntax verwendet. Mit fread verfügt das Paket auch über eine außergewöhnlich schnelle und benutzerfreundliche Ladefunktion:

require(data.table)
Start <- Sys.time()
daten <- fread("2008b.csv")
Ende <- Sys.time()
Zeit_fread <- Ende - Start
cat("n Laufzeit fread, 1.000.000 Zeilen: ", Zeit_fread, "Sekunden")

fread aus dem data.table-Paket gewinnt hier beim csv-Format vor dem readr-Paket mit Zeiten um 1,4 Sekunden.

Fazit: Laden großer Exceldateien in R

Viele Pakete sind in der Lage, Exceldaten in R zu laden. Die Ladezeiten unterscheiden sich dabei drastisch, je nachdem, wie die Schnittstelle zu Excel „unter der Haube“ programmiert wurde. readxl erwies sich beim .xlsx-Format als das schnellste Paket. Für größere Datenmengen empfehle ich jedoch den Umstieg auf andere Dateiformate. Beispielsweise werden .csv-Formate sehr viel schneller geladen. Hier gewann data.table vor readr. Außerdem kann R mit Datenbanken arbeiten, dazu gibt es viele Pakete (zum Beispiel DBI, RMySQL). Das bekannte dplyr-Paket erlaubt es beispielsweise, die gleichen R-Befehle, die auf R-interne Daten angewendet werden, auch an Datenbanken zu schicken. Man muss dazu lediglich eine Datenbankverbindung definieren und benötigt keine SQL-Befehle.

Sie möchten Ihre R-Fähigkeiten verbessern? Gern bereite ich einen Workshop für Sie und/oder Ihre Mitarbeiter vor.




Ein Gedanke zu „Excel-Datensätze in R laden: Geschwindigkeits-Test verschiedener R-Pakete“

Freue mich über Kommentare!