La manipulation de java.lang.OutOfMemoryError lors de l'écriture dans Excel à partir de R
La xlsx
emballage peut être utilisé pour lire et écrire des feuilles de calcul Excel à partir de R. Malheureusement, même modérée de grandes feuilles de calcul, java.lang.OutOfMemoryError
peut se produire. En particulier,
## Error in .jcall("RJavaTools", "Ljava/lang/Object;", "invokeMethod", cl, :
## java.lang.OutOfMemoryError: Java heap space
## Error in .jcall("RJavaTools", "Ljava/lang/Object;", "newInstance", .jfindClass(class), :
## java.lang.OutOfMemoryError: GC overhead limit exceeded
(D'autres exceptions sont également possibles mais plus rares.)
Une question semblable a été posée au sujet de cette erreur lors de la lecture des feuilles de calcul.
L'importation d'un gros fichier xlsx dans R?
Le principal avantage de l'utilisation de feuilles de calcul Excel en tant que support de stockage de données de plus de CSV est que vous pouvez stocker plusieurs feuilles d'un même fichier, de sorte que l'on considère ici une liste de trames de données d'être écrit une trame de données par feuille de calcul. Cet exemple de jeu de données contient 40 trames de données, chacune avec deux colonnes jusqu'à 200k lignes. Il est conçu pour être suffisamment grand pour être problématique, mais vous pouvez changer la taille en modifiant n_sheets
et n_rows
.
library(xlsx)
set.seed(19790801)
n_sheets <- 40
the_data <- replicate(
n_sheets,
{
n_rows <- sample(2e5, 1)
data.frame(
x = runif(n_rows),
y = sample(letters, n_rows, replace = TRUE)
)
},
simplify = FALSE
)
names(the_data) <- paste("Sheet", seq_len(n_sheets))
La méthode naturelle de l'écriture de ce fichier est de créer un classeur à l'aide de createWorkbook
, puis une boucle sur chaque bloc de données d'appel createSheet
et addDataFrame
. Enfin du classeur peuvent être écrites dans le fichier à l'aide de saveWorkbook
. J'ai ajouté des messages à la boucle pour le rendre plus facile de voir où il tombe.
wb <- createWorkbook()
for(i in seq_along(the_data))
{
message("Creating sheet", i)
sheet <- createSheet(wb, sheetName = names(the_data)[i])
message("Adding data frame", i)
addDataFrame(the_data[[i]], sheet)
}
saveWorkbook(wb, "test.xlsx")
L'exécution de ce en 64 bits sur une machine avec 8 go de RAM, il jette la GC overhead limit exceeded
d'erreur lors de l'exécution de addDataFrame
pour la première fois.
Comment puis-je écrire de grands ensembles de données de feuilles de calcul Excel à l'aide de xlsx
?
Vous devez vous connecter pour publier un commentaire.
C'est un problème connu:
http://code.google.com/p/rexcel/issues/detail?id=33
Tout en suspens, la question de la page des liens vers une solution par Gabor Grothendieck ce qui suggère que la taille du tas devrait être accrue par la mise en au
java.parameters
option avant lerJava
package est chargé. (rJava
est une dépendance dexlsx
.)La valeur
1000
est le nombre de méga-octets de RAM pour permettre le tas Java; elle peut être remplacée par une valeur que vous désirez. Mes expériences avec cette suggèrent que les plus grandes valeurs sont meilleures, et vous pouvez heureusement utilisation complète de votre RAM droit. Par exemple, j'ai obtenu les meilleurs résultats à l'aide de:sur la machine avec 8 go de RAM.
Une amélioration peut être obtenue en demandant la collecte des ordures à chaque itération de la boucle. Comme le fait remarquer @gjabel, R la collecte des ordures peuvent être effectuées à l'aide de
gc()
. On peut définir une Java de collecte des ordures fonction qui appelle la JavaSystem.gc()
méthode:Puis la boucle peut être mis à jour à:
Avec ces deux corrections de code, le code courait jusqu'
i = 29
avant de lancer une erreur.Une technique que j'ai essayé, sans succès, a été d'utiliser
write.xlsx2
pour écrire le contenu de fichier à chaque itération. Cela a été plus lent que le code des autres, et elle a diminué au cours de la 10ème itération (mais au moins une partie du contenu a été écrit dans le fichier).xlsx
package pour leopenxlsx
paquet, qui dépend deRcpp
plutôt que de Java.readxl
est une autre nouvelle C/C++ alternative qui semble prometteur.options(java.parameters = "-Xmx8000m")
avant de chargerrJava
,xlsxjars
,xlsx
résoluError in .jcall("RJavaTools", "Ljava/lang/Object;", "invokeMethod", cl, : org.apache.poi.POIXMLException: java.lang.reflect.InvocationTargetException Calls: getNetwork ... <Anonymous> -> .jrcall -> .jcall -> .jcheck -> .Call Execution halted
dans RHEL 6.3 x86_64, java 1.7.0_79 (Oracle), rJava_0.9-7, xlsxjars_0.6.0, xlsx_0.5.7Bâtiment sur @richie-coton réponse, j'ai trouvé l'ajout de
gc()
à lajgc
fonction gardé l'utilisation du PROCESSEUR faible.Mon précédent
for
la boucle a toujours eu du mal avec l'originaljgc
fonction, mais avec un supplément de commande, je n'ai plus à courir dansGC overhead limit exceeded
message d'erreur.Solution pour l'erreur ci-dessus:
Veuillez utiliser le mentionnés ci-dessous r - code:
détacher(forfait:xlsx)
détacher(forfait:XLConnect)
bibliothèque(openxlsx)
Et essayez d'importer le fichier de nouveau, et vous n'aurez plus d'erreur que cela fonctionne pour moi.
Vous pouvez également utiliser gc() à l'intérieur de la boucle si vous êtes l'écriture ligne par ligne. gc() se tient pour la collecte des ordures. gc() peut être utilisée en cas de problème de mémoire.