Eine große XLSX-Datei in R importieren?

74

Ich frage mich, ob jemand eine Möglichkeit kennt, Daten aus einer "großen" xlsx-Datei (~ 20 MB) zu importieren. Ich habe versucht, xlsx- und XLConnect-Bibliotheken zu verwenden. Leider verwenden beide rJava und ich erhalte immer den gleichen Fehler:

> library(XLConnect)
> wb <- loadWorkbook("MyBigFile.xlsx")
Error: OutOfMemoryError (Java): Java heap space

oder

> library(xlsx)
> mydata <- read.xlsx2(file="MyBigFile.xlsx")
Error in .jcall("RJavaTools", "Ljava/lang/Object;", "invokeMethod", cl,  : 
   java.lang.OutOfMemoryError: Java heap space

Ich habe auch versucht, die java.parameters vor dem Laden von rJava zu ändern:

> options( java.parameters = "-Xmx2500m")
> library(xlsx) # load rJava
> mydata <- read.xlsx2(file="MyBigFile.xlsx")
Error in .jcall("RJavaTools", "Ljava/lang/Object;", "invokeMethod", cl,  : 
   java.lang.OutOfMemoryError: Java heap space

oder nach dem Laden von rJava (das ist ein bisschen dumm, denke ich):

> library(xlsx) # load rJava
> options( java.parameters = "-Xmx2500m")
> mydata <- read.xlsx2(file="MyBigFile.xlsx")
Error in .jcall("RJavaTools", "Ljava/lang/Object;", "invokeMethod", cl,  : 
   java.lang.OutOfMemoryError: Java heap space

Aber nichts funktioniert. Hat jemand eine Idee?

user2722443
quelle
5
Haben Sie darüber nachgedacht, Ihre Daten in einem universelleren Format zu speichern, z. B. CSV?
Flodel
3
gdataist eine andere Option. Ich glaube, es basiert nicht auf Java, aber ich könnte mich irren.
Ricardo Saporta
2
Warum ist es so groß? Viele Zeilen (brauchen Sie alle?), Viele Spalten (brauchen Sie alle?), Viele einzelne Blätter (brauchen Sie alle?), Ein hochauflösendes eingebettetes Bild (das brauchen Sie nicht) ...)? Bei Tabellenkalkulations- und anderen Binärdateien ist die Größe der Datei in Byte oft kein nützliches Maß dafür, wie groß die darin enthaltenen Daten tatsächlich sind.
Spacedman
3
gdatafunktioniert ... sehr langsam, ca. 7 min pro Blatt, aber es funktioniert.
user2722443
3
Ich habe daran gearbeitet, die monströse, formelreiche Excel-Datei eines Kollegen (150 MB) zu importieren, und gdatawar das einzige Excel-Paket, das es schaffen konnte. Wie hier ging Java-basierten Paketen der Speicherplatz aus; openxlsxfehlerhaft. gdataEs dauerte 30 Minuten pro Blatt, aber es hat die Arbeit erledigt.
Matt Parker

Antworten:

141

Ich bin auf diese Frage gestoßen, als mir jemand (noch eine) Excel-Datei zur Analyse geschickt hat. Dieser ist nicht einmal so groß, aber aus irgendeinem Grund stieß ich auf einen ähnlichen Fehler:

java.lang.OutOfMemoryError: GC overhead limit exceeded

Basierend auf dem Kommentar von @Dirk Eddelbuettel in einer früheren Antwort habe ich das openxlsx-Paket installiert ( http://cran.r-project.org/web/packages/openxlsx/ ). und lief dann:

library("openxlsx")
mydf <- read.xlsx("BigExcelFile.xlsx", sheet = 1, startRow = 2, colNames = TRUE)

Es war genau das, wonach ich gesucht habe. Einfach zu bedienen und schnell böse. Es ist meine neue BFF. Danke für den Tipp @Dirk E!

Übrigens, ich möchte diese Antwort von Dirk E nicht abwerben. Wenn er also eine Antwort veröffentlicht, akzeptieren Sie diese bitte und nicht meine!

Orville Jackson
quelle
Ich habe so viele Methoden ausprobiert, um eine große .xslx-Datei zu lesen, aber nichts schien für mich zu funktionieren. Ich habe eine Fehlermeldung erhalten, als ich die Funktion von Schaun Wheeler bei github verwendet habe, und konnte nicht herausfinden, wie der Befehl perl in gdata für meinen Computer verwendet wird. 'openxlsx "ist so ein Lebensretter für mich. Danke @Dirk Eddelbuettel und Orville Jackson.
Nasia Jaffri
Kennen Sie eine andere Lösung? Ich kann keine Möglichkeit finden, XLS-Dateien mit openxlsx zu öffnen
user124123
Sie können die Funktion read.xls im Paket gdata ausprobieren. Ich habe es nie selbst benutzt, aber einen Versuch wert.
Orville Jackson
1
openxlsx ist die einzige Bibliothek, die für meine Excel-Datei (70Mo) funktioniert hat. aber ich musste zuerst von .xls zu .xlsx konvertieren
agenis
OpenXLSX hat den Nachteil, dass es keine Daten erkennt. Read_excel aus dem Paket readxl scheint mir der richtige Weg zu sein.
Peer
14
options(java.parameters = "-Xmx2048m")  ## memory set to 2 GB
library(XLConnect)

Ermöglichen Sie mehr Speicher mit "Optionen", bevor eine Java-Komponente geladen wird. Laden Sie dann die XLConnect-Bibliothek (sie verwendet Java).

Das ist es. Beginnen Sie mit dem Einlesen von Daten mit readWorksheet .... und so weiter. :) :)

Viquanto
quelle
1
Danke für den Tipp. Wichtig zu beachten: Ich musste das options(java.parameters = "-Xmx2048m")vor dem Ausstellen ausgeben, require('rJava')wenn ich dies in R-Studio verwendete. Leider wird jetzt ein neuer Fehler angezeigt: "java.lang.OutOfMemoryError: GC-Overhead-Limit überschritten", aber das ist sicher ein anderes Problem.
Pbnelson
Das ist für mich gearbeitet, aber ich musste auch sicher , dass meine R - Version angepasst meine Java - Version (zB sowohl 64-Bit) machen, und den Java - Pfad richtig eingestellt: options(java.parameters="-Xmx4g") # increase java memory, Sys.setenv(JAVA_HOME='C:\\Program Files\\Java\\jdk-11.0.2') # for 64-bit version,library(rJava) # check it works
Simon Woodward
8

Ich stimme der Antwort von @orville jackson zu und es hat mir auch sehr geholfen.

Inline zu der Antwort von @orville jackson. Hier finden Sie eine detaillierte Beschreibung, wie Sie openxlsx zum Lesen und Schreiben großer Dateien verwenden können.

Wenn die Datengröße klein ist, verfügt R über viele Pakete und Funktionen, die gemäß Ihren Anforderungen verwendet werden können.

write.xlsx, write.xlsx2, XLconnect erledigen ebenfalls die Arbeit, aber diese sind im Vergleich zu openxlsx manchmal langsam.

Also, wenn Sie mit den großen Datenmengen zu tun haben und auf Java-Fehler gestoßen sind. Ich würde vorschlagen, einen Blick auf "openxlsx" zu werfen, was wirklich großartig ist und die Zeit um 1/12 verkürzt.

Ich habe alle getestet und war schließlich sehr beeindruckt von der Leistung der openxlsx-Funktionen.

Hier sind die Schritte zum Schreiben mehrerer Datensätze in mehrere Blätter.

install.packages("openxlsx")
library("openxlsx")

start.time <- Sys.time()

# Creating large data frame
x <- as.data.frame(matrix(1:4000000,200000,20))
y <- as.data.frame(matrix(1:4000000,200000,20))
z <- as.data.frame(matrix(1:4000000,200000,20))

# Creating a workbook
wb <- createWorkbook("Example.xlsx")
Sys.setenv("R_ZIPCMD" = "C:/Rtools/bin/zip.exe") ## path to zip.exe

Sys.setenv ("R_ZIPCMD" = "C: /Rtools/bin/zip.exe") muss statisch sein, da es auf ein Dienstprogramm von Rtools verweist.

Hinweis: Wenn Rtools nicht auf Ihrem System installiert ist, installieren Sie es bitte zuerst, um einen reibungslosen Ablauf zu gewährleisten. Hier ist der Link als Referenz: (Wählen Sie die entsprechende Version) https://cran.r-project.org/bin/windows/Rtools/

Aktivieren Sie die Optionen gemäß dem folgenden Link (aktivieren Sie während der Installation alle Kontrollkästchen) https://cloud.githubusercontent.com/assets/7400673/12230758/99fb2202-b8a6-11e5-82e6-836159440831.png

# Adding a worksheets : parameters for addWorksheet are 1. Workbook Name 2. Sheet Name

addWorksheet(wb, "Sheet 1")
addWorksheet(wb, "Sheet 2")
addWorksheet(wb, "Sheet 3")

# Writing data in to respetive sheets: parameters for writeData are 1. Workbook Name 2. Sheet index/ sheet name 3. dataframe name

writeData(wb, 1, x)

# incase you would like to write sheet with filter available for ease of access you can pass the parameter withFilter = TRUE in writeData function.
writeData(wb, 2, x = y, withFilter = TRUE)

## Similarly writeDataTable is another way for representing your data with table formatting:

writeDataTable(wb, 3, z)

saveWorkbook(wb, file = "Example.xlsx", overwrite = TRUE)

end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken

Das openxlsx-Paket eignet sich hervorragend zum Lesen und Schreiben großer Datenmengen aus / in Excel-Dateien und bietet zahlreiche Optionen für die benutzerdefinierte Formatierung in Excel.

Die interessante Tatsache ist, dass wir uns hier nicht um Java-Heap-Speicher kümmern müssen.

Ayush Varshney
quelle
Getestete read.xlsx2, XLConnect, readxl und openxlsx und openxlsx ist um ein Vielfaches schneller als andere
Ali
7

Ich weiß, dass diese Frage etwas alt ist, aber dafür gibt es heutzutage eine gute Lösung. Dies ist ein Standardpaket, wenn Sie versuchen, Excel in Rstudio mit GUI zu importieren, und es funktioniert in meiner Situation gut.

library(readxl)

data <- read_excel(filename)
Doongsil
quelle
5

Wie in der kanonischen Excel-> R-Frage erwähnt , stammt eine neue Alternative aus dem readxlPaket, das sich im Vergleich zu z . B. openxlsxund als ziemlich schnell herausgestellt hat xlsx.

Das heißt, es gibt eine bestimmte Grenze für die Größe der Tabellenkalkulation, über die Sie wahrscheinlich besser dran sind, wenn Sie das Ding einfach als speichern .csvund verwenden fread.

MichaelChirico
quelle
3

Ich hatte auch den gleichen Fehler in beiden xlsx::read.xlsxund XLConnect::readWorksheetFromFile. Vielleicht können Sie RODBC::odbcDriverConnectund verwenden RODBC::sqlFetch, das Microsoft RODBC verwendet, das viel effizienter ist.

Jingnan Li
quelle
2

Der Vorschlag von @ flodel, auf CSV umzusteigen, scheint am einfachsten zu sein. Wenn dies aus irgendeinem Grund keine Option ist, können Sie die Datei in Blöcken einlesen:

 require(XLConnect)
 chnksz <- 2e3
 s <- <sheet>
 wb <- loadWorkbook(<file>, s)
 tot.rows <- getLastRow(wb)
 last.row =0
 for (i in seq(ceiling( tot.rows / chnksz) )) {
    next.batch <- readWorksheet(wb, s, startRow=last.row+i, endRow=last.row+chnksz+i)
    # optionally save next.batch to disk or 
    # assign it to a list. See which works for you. 
 } 
Ricardo Saporta
quelle
Leider loadWorkbookgeneriert der Befehl einen "OutOfMemoryError". Mit der gleichen Idee habe ich es versucht mydata.chunk = read.xlsx2(file="MyBigFile.xlsx", sheetIndex=1, startRow=1, endRow=10), aber es ist immer noch der gleiche Fehler.
user2722443
@ user2722443, speichern Sie die Teile, die Sie eingelesen haben, und entfernen sie dann aus dem Speicher? Versuchen Sie auch, gc()in jeder for-Schleife zu laufen . Es wird Sie verlangsamen, aber etwas Speicher löschen. Sind Sie sich übrigens sicher, dass die Konvertierung in CSV nicht in Frage kommt?
Ricardo Saporta
1
@ {Ricardo Saporta} mydata.chunk = read.xlsx2(file="MyBigFile.xlsx", sheetIndex=1, startRow=1, endRow=10)generiert tatsächlich einen "OutOfMemoryError". Ich kann also nichts entfernen. In Bezug auf die CSV-Konvertierung kommt dies nicht völlig in Frage, sondern ist eine externe Operation (vor dem Laden in R).
user2722443
0

Ich fand diesen Thread auf der Suche nach einer Antwort auf genau die gleiche Frage. Anstatt zu versuchen, eine XLSX-Datei aus R heraus zu hacken, funktionierte es für mich, die Datei mit Python in CSV zu konvertieren und sie dann mit einer Standard-Scanfunktion in R zu importieren.

Überprüfen Sie heraus: https://github.com/dilshod/xlsx2csv

Aaron
quelle
1
... was seit einem Jahrzehnt im gdata-Paket für R verfügbar ist (aber Perl hinter den Kulissen verwendet).
Dirk Eddelbuettel
Als ich mit gdata an dem Problem arbeitete, war es inakzeptabel langsam. Dieses Python-Skript konvertiert große XLSX-Dateien extrem schnell
Aaron
1
Wie unterscheidet sich diese Antwort von dem Vorschlag von @ flodel, der in einer anderen Antwort erwähnt wird? IMHO RODBC hat wenige Vorteile gegenüber dem mittleren CSV-Format.
Mlt
8
Es gibt auch ein neues Kind auf dem Block: openxlsx , das nur Rcpp und nichts als C ++ - Code verwendet - und behauptet, sehr schnell zu sein. Ich bin mir nicht sicher, wie raffiniert es ist.
Dirk Eddelbuettel
Warum würden Sie es nicht einfach in Excel öffnen und in CSV exportieren?
MattE