web-dev-qa-db-fra.com

Astuces pour gérer la mémoire disponible dans une session R

Quelles astuces les gens utilisent-ils pour gérer la mémoire disponible d'une session R interactive? J'utilise les fonctions ci-dessous [basées sur les contributions de Petr Pikal et David Hinds à la liste de r-help en 2004] pour répertorier (et/ou trier) les objets les plus volumineux et pour occasionnellement rm() certains d'entre eux. Mais, de loin, la solution la plus efficace consistait à… fonctionner sous Linux 64 bits avec une mémoire suffisante.

Y a-t-il d'autres astuces que les gens veulent partager? Un par poste, s'il vous plaît.

# improved list of objects
.ls.objects <- function (pos = 1, pattern, order.by,
                        decreasing=FALSE, head=FALSE, n=5) {
    napply <- function(names, fn) sapply(names, function(x)
                                         fn(get(x, pos = pos)))
    names <- ls(pos = pos, pattern = pattern)
    obj.class <- napply(names, function(x) as.character(class(x))[1])
    obj.mode <- napply(names, mode)
    obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
    obj.size <- napply(names, object.size)
    obj.dim <- t(napply(names, function(x)
                        as.numeric(dim(x))[1:2]))
    vec <- is.na(obj.dim)[, 1] & (obj.type != "function")
    obj.dim[vec, 1] <- napply(names, length)[vec]
    out <- data.frame(obj.type, obj.size, obj.dim)
    names(out) <- c("Type", "Size", "Rows", "Columns")
    if (!missing(order.by))
        out <- out[order(out[[order.by]], decreasing=decreasing), ]
    if (head)
        out <- head(out, n)
    out
}
# shorthand
lsos <- function(..., n=10) {
    .ls.objects(..., order.by="Size", decreasing=TRUE, head=TRUE, n=n)
}
476
Dirk Eddelbuettel

Pour illustrer davantage la stratégie commune des redémarrages fréquents, nous pouvons utiliser littler qui nous permet d’exécuter des expressions simples directement à partir de la ligne de commande. Voici un exemple que j’utilise parfois pour chronométrer différents BLAS pour un produit croisé simple.

 r -e'N<-3*10^3; M<-matrix(rnorm(N*N),ncol=N); print(system.time(crossprod(M)))'

Également,

 r -lMatrix -e'example(spMatrix)'

charge le package Matrix (via le commutateur --packages | -l) et exécute les exemples de la fonction spMatrix. Comme r est toujours "frais", cette méthode est également un bon test lors du développement du paquet.

Enfin et surtout, r fonctionne également très bien pour le mode de traitement par lots automatisé dans les scripts utilisant l’en-tête Shebang '#!/Usr/bin/r'. Rscript est une alternative lorsque littler est indisponible (par exemple sous Windows).

25
Dirk Eddelbuettel

Assurez-vous d’enregistrer votre travail dans un script reproductible. De temps en temps, rouvrez R, puis source() votre script. Vous supprimerez tout ce que vous n'utiliserez plus et, comme avantage supplémentaire, vous aurez testé votre code.

186
hadley

J'utilise le package data.table . Avec son opérateur :=, vous pouvez:

  • Ajouter des colonnes par référence
  • Modifier des sous-ensembles de colonnes existantes par référence et par groupe par référence
  • Supprimer les colonnes par référence

Aucune de ces opérations ne copie le (potentiellement grand) data.table du tout, pas une seule fois.

  • L'agrégation est également particulièrement rapide car data.table utilise beaucoup moins de mémoire de travail.

Liens connexes :

154
Matt Dowle

Vu ceci sur un post Twitter et pense que c'est une fonction géniale de Dirk! Pour faire suite à la réponse de JD Long, je voudrais faire ceci pour une lecture conviviale:

# improved list of objects
.ls.objects <- function (pos = 1, pattern, order.by,
                        decreasing=FALSE, head=FALSE, n=5) {
    napply <- function(names, fn) sapply(names, function(x)
                                         fn(get(x, pos = pos)))
    names <- ls(pos = pos, pattern = pattern)
    obj.class <- napply(names, function(x) as.character(class(x))[1])
    obj.mode <- napply(names, mode)
    obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
    obj.prettysize <- napply(names, function(x) {
                           format(utils::object.size(x), units = "auto") })
    obj.size <- napply(names, object.size)
    obj.dim <- t(napply(names, function(x)
                        as.numeric(dim(x))[1:2]))
    vec <- is.na(obj.dim)[, 1] & (obj.type != "function")
    obj.dim[vec, 1] <- napply(names, length)[vec]
    out <- data.frame(obj.type, obj.size, obj.prettysize, obj.dim)
    names(out) <- c("Type", "Size", "PrettySize", "Length/Rows", "Columns")
    if (!missing(order.by))
        out <- out[order(out[[order.by]], decreasing=decreasing), ]
    if (head)
        out <- head(out, n)
    out
}

# shorthand
lsos <- function(..., n=10) {
    .ls.objects(..., order.by="Size", decreasing=TRUE, head=TRUE, n=n)
}

lsos()

Ce qui donne quelque chose comme ce qui suit:

                      Type   Size PrettySize Length/Rows Columns
pca.res                 PCA 790128   771.6 Kb          7      NA
DF               data.frame 271040   264.7 Kb        669      50
factor.AgeGender   factanal  12888    12.6 Kb         12      NA
dates            data.frame   9016     8.8 Kb        669       2
sd.                 numeric   3808     3.7 Kb         51      NA
napply             function   2256     2.2 Kb         NA      NA
lsos               function   1944     1.9 Kb         NA      NA
load               loadings   1768     1.7 Kb         12       2
ind.sup             integer    448  448 bytes        102      NA
x                 character     96   96 bytes          1      NA

NOTE: La partie principale que j'ai ajoutée était (encore une fois, adaptée de la réponse de JD):

obj.prettysize <- napply(names, function(x) {
                           print(object.size(x), units = "auto") })
106
Tony Breyal

Je fais un usage agressif du paramètre subset en ne sélectionnant que les variables requises lors de la transmission d'images de données à l'argument data= des fonctions de régression. Cela entraîne certaines erreurs si j'oublie d'ajouter des variables à la fois à la formule et au vecteur select=, mais cela permet néanmoins de gagner beaucoup de temps en raison de la diminution de la copie d'objets et de réduire considérablement l'encombrement de la mémoire. Supposons que j'ai 4 millions d'enregistrements avec 110 variables (et moi si.) Exemple:

# library(rms); library(Hmisc) for the cph,and rcs functions
Mayo.PrCr.rbc.mdl <- 
cph(formula = Surv(surv.yr, death) ~ age + Sex + nsmkr + rcs(Mayo, 4) + 
                                     rcs(PrCr.rat, 3) +  rbc.cat * Sex, 
     data = subset(set1HLI,  gdlab2 & HIVfinal == "Negative", 
                           select = c("surv.yr", "death", "PrCr.rat", "Mayo", 
                                      "age", "Sex", "nsmkr", "rbc.cat")
   )            )

En guise de contexte et de stratégie, la variable gdlab2 est un vecteur logique construit pour les sujets d'un jeu de données contenant toutes les valeurs normales ou presque normales pour un ensemble de tests de laboratoire et HIVfinal vecteur de caractères qui résume les tests préliminaires et de confirmation du VIH.

48
42-

J'adore le script .ls.objects () de Dirk, mais j'ai continué à plisser les yeux pour compter les caractères dans la colonne de taille. J'ai donc fait quelques trucs laids pour le rendre présent avec un joli formatage pour la taille:

.ls.objects <- function (pos = 1, pattern, order.by,
                        decreasing=FALSE, head=FALSE, n=5) {
    napply <- function(names, fn) sapply(names, function(x)
                                         fn(get(x, pos = pos)))
    names <- ls(pos = pos, pattern = pattern)
    obj.class <- napply(names, function(x) as.character(class(x))[1])
    obj.mode <- napply(names, mode)
    obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
    obj.size <- napply(names, object.size)
    obj.prettysize <- sapply(obj.size, function(r) prettyNum(r, big.mark = ",") )
    obj.dim <- t(napply(names, function(x)
                        as.numeric(dim(x))[1:2]))
    vec <- is.na(obj.dim)[, 1] & (obj.type != "function")
    obj.dim[vec, 1] <- napply(names, length)[vec]
    out <- data.frame(obj.type, obj.size,obj.prettysize, obj.dim)
    names(out) <- c("Type", "Size", "PrettySize", "Rows", "Columns")
    if (!missing(order.by))
        out <- out[order(out[[order.by]], decreasing=decreasing), ]
        out <- out[c("Type", "PrettySize", "Rows", "Columns")]
        names(out) <- c("Type", "Size", "Rows", "Columns")
    if (head)
        out <- head(out, n)
    out
}
48
JD Long

C'est un bon truc.

Une autre suggestion consiste à utiliser autant que possible des objets économes en mémoire: utilisez par exemple une matrice plutôt qu'un data.frame.

Cela ne concerne pas vraiment la gestion de la mémoire, mais une fonction importante peu connue est memory.limit (). Vous pouvez augmenter la valeur par défaut à l'aide de cette commande, memory.limit (size = 2500), où la taille est exprimée en Mo. Comme Dirk l'a mentionné, vous devez utiliser 64 bits pour en tirer un avantage réel.

33
Shane

J'aime beaucoup la fonction améliorée des objets développée par Dirk. La plupart du temps cependant, une sortie plus basique avec le nom et la taille de l'objet me suffit. Voici une fonction plus simple avec un objectif similaire. L'utilisation de la mémoire peut être ordonnée par ordre alphabétique ou par taille, peut être limitée à un certain nombre d'objets et peut être ordonnée par ordre croissant ou décroissant. De plus, je travaille souvent avec des données de 1 Go +, alors la fonction change d'unité en conséquence.

showMemoryUse <- function(sort="size", decreasing=FALSE, limit) {

  objectList <- ls(parent.frame())

  oneKB <- 1024
  oneMB <- 1048576
  oneGB <- 1073741824

  memoryUse <- sapply(objectList, function(x) as.numeric(object.size(eval(parse(text=x)))))

  memListing <- sapply(memoryUse, function(size) {
        if (size >= oneGB) return(paste(round(size/oneGB,2), "GB"))
        else if (size >= oneMB) return(paste(round(size/oneMB,2), "MB"))
        else if (size >= oneKB) return(paste(round(size/oneKB,2), "kB"))
        else return(paste(size, "bytes"))
      })

  memListing <- data.frame(objectName=names(memListing),memorySize=memListing,row.names=NULL)

  if (sort=="alphabetical") memListing <- memListing[order(memListing$objectName,decreasing=decreasing),] 
  else memListing <- memListing[order(memoryUse,decreasing=decreasing),] #will run if sort not specified or "size"

  if(!missing(limit)) memListing <- memListing[1:limit,]

  print(memListing, row.names=FALSE)
  return(invisible(memListing))
}

Et voici un exemple de sortie:

> showMemoryUse(decreasing=TRUE, limit=5)
      objectName memorySize
       coherData  713.75 MB
 spec.pgram_mine  149.63 kB
       stoch.reg  145.88 kB
      describeBy    82.5 kB
      lmBandpass   68.41 kB
31
Michael Hallquist

Malheureusement, je n'ai pas eu le temps de le tester de manière approfondie, mais voici un conseil mémoire que je n'ai jamais vu auparavant. Pour moi, la mémoire requise a été réduite de plus de 50%. Lorsque vous lisez des éléments dans R avec, par exemple, read.csv, ils nécessitent une certaine quantité de mémoire. Après cela, vous pourrez les enregistrer avec save("Destinationfile",list=ls()) lors de votre prochaine ouverture de R, vous pourrez utiliser load("Destinationfile") Il est possible que l'utilisation de la mémoire ait diminué. Ce serait bien si quelqu'un pouvait confirmer si cela produisait des résultats similaires avec un jeu de données différent.

30

Je ne sauve jamais un espace de travail R. J'utilise des scripts d'importation et des scripts de données et génère tous les objets de données particulièrement volumineux que je ne souhaite pas recréer souvent dans des fichiers. De cette façon, je commence toujours par un nouvel espace de travail et je n'ai pas besoin de nettoyer les gros objets. C'est une très belle fonction cependant.

29
kpierce8

Pour des raisons de rapidité et de mémoire, lors de la construction d'un bloc de données volumineux via une série d'étapes complexes, je le viderai périodiquement (le fichier en cours de construction en cours de création) sur le disque, en ajoutant à tout ce qui était auparavant, puis en le redémarrant. . De cette façon, les étapes intermédiaires ne fonctionnent que sur de petites trames de données (ce qui est bien, par exemple, rbind ralentit considérablement avec des objets plus volumineux). L'ensemble du jeu de données peut être relu à la fin du processus, lorsque tous les objets intermédiaires ont été supprimés.

dfinal <- NULL
first <- TRUE
tempfile <- "dfinal_temp.csv"
for( i in bigloop ) {
    if( !i %% 10000 ) { 
        print( i, "; flushing to disk..." )
        write.table( dfinal, file=tempfile, append=!first, col.names=first )
        first <- FALSE
        dfinal <- NULL   # nuke it
    }

    # ... complex operations here that add data to 'dfinal' data frame  
}
print( "Loop done; flushing to disk and re-reading entire data set..." )
write.table( dfinal, file=tempfile, append=TRUE, col.names=FALSE )
dfinal <- read.table( tempfile )
23
Ben B-L

Il suffit de noter que le tables() du paquet data.table semble être un très bon substitut pour la fonction personnalisée .ls.objects() de Dirk (détaillée dans les réponses précédentes), bien que cela ne concerne que les données.frames/tables et pas p. Ex. matrices, tableaux, listes.

17
geotheory
  1. J'ai la chance et mes grands ensembles de données sont sauvegardés par l'instrument en "morceaux" (sous-ensembles) d'environ 100 Mo (32 bits en binaire). Ainsi, je peux effectuer des étapes de pré-traitement (suppression de parties non informatives, sous-échantillonnage) séquentiellement avant de fusionner le jeu de données.

  2. L'appel de gc () "à la main" peut aider si la taille des données se rapproche de la mémoire disponible.

  3. Parfois, un algorithme différent nécessite beaucoup moins de mémoire.
    Il existe parfois un compromis entre la vectorisation et l’utilisation de la mémoire.
    compare: split & lapply par rapport à une boucle for.

  4. Par souci d’analyse rapide et facile des données, je travaille souvent d’abord avec un petit sous-ensemble aléatoire (sample ()) des données. Une fois que le script d'analyse de données/.Rnw est terminé, le code d'analyse de données et les données complètes sont acheminés vers le serveur de calcul pour un calcul nuit/week-end/....

14
cbeleites

Utilisation d'environnements au lieu de listes pour gérer des collections d'objets occupant une quantité importante de mémoire de travail.

La raison: chaque fois qu'un élément de la structure list est modifié, la liste entière est dupliquée temporairement. Cela devient un problème si les besoins en stockage de la liste correspondent à environ la moitié de la mémoire de travail disponible, car les données doivent ensuite être échangées sur le disque dur lent. Les environnements, en revanche, ne sont pas soumis à ce comportement et peuvent être traités comme des listes.

Voici un exemple:

get.data <- function(x)
{
  # get some data based on x
  return(paste("data from",x))
}

collect.data <- function(i,x,env)
{
  # get some data
  data <- get.data(x[[i]])
  # store data into environment
  element.name <- paste("V",i,sep="")
  env[[element.name]] <- data
  return(NULL)  
}

better.list <- new.env()
filenames <- c("file1","file2","file3")
lapply(seq_along(filenames),collect.data,x=filenames,env=better.list)

# read/write access
print(better.list[["V1"]])
better.list[["V2"]] <- "testdata"
# number of list elements
length(ls(better.list))

En conjonction avec des structures telles que big.matrix ou data.table permettant de modifier leur contenu sur place, une utilisation très efficace de la mémoire peut être obtenue.

11
Georg Schnabel

La fonction ll dans le package gData peut également afficher l'utilisation de la mémoire de chaque objet.

gdata::ll(unit='MB')
7
user1436187

Si vous voulez vraiment éviter les fuites, évitez de créer de gros objets dans l'environnement global.

Ce que je fais habituellement est d’avoir une fonction qui effectue le travail et retourne NULL - toutes les données sont lues et manipulées dans cette fonction ou dans d’autres qu’elle appelle.

6
Alexander Radev

Cela n’ajoute rien à ce qui précède, mais est écrit dans le style simple et très commenté que j’aime. Cela donne un tableau avec les objets ordonnés en taille, mais sans certains des détails donnés dans les exemples ci-dessus:

#Find the objects       
MemoryObjects = ls()    
#Create an array
MemoryAssessmentTable=array(NA,dim=c(length(MemoryObjects),2))
#Name the columns
colnames(MemoryAssessmentTable)=c("object","bytes")
#Define the first column as the objects
MemoryAssessmentTable[,1]=MemoryObjects
#Define a function to determine size        
MemoryAssessmentFunction=function(x){object.size(get(x))}
#Apply the function to the objects
MemoryAssessmentTable[,2]=t(t(sapply(MemoryAssessmentTable[,1],MemoryAssessmentFunction)))
#Produce a table with the largest objects first
noquote(MemoryAssessmentTable[rev(order(as.numeric(MemoryAssessmentTable[,2]))),])
5
JamesF

C'est une réponse plus récente à cette excellente vieille question. De Hadley's Advanced R:

install.packages("pryr")

library(pryr)

object_size(1:10)
## 88 B

object_size(mean)
## 832 B

object_size(mtcars)
## 6.74 kB

( http://adv-r.had.co.nz/memory.html )

4
Chris Beeley

Si vous travaillez sur Linux et que vous souhaitez utiliser plusieurs processus et que vous devez uniquement faire lire des opérations sur un ou plusieurs objets volumineux utilisez makeForkCluster au lieu de makePSOCKcluster. Cela vous fait également gagner du temps lors de l'envoi de l'objet volumineux aux autres processus.

3
gdkrmr

J'apprécie vraiment certaines des réponses ci-dessus, après @hadley et @Dirk, qui suggèrent de fermer R et d'émettre source et d'utiliser la ligne de commande pour proposer une solution qui a très bien fonctionné pour moi. J'ai eu à traiter avec des centaines de spectres de masse, chacun occupant environ 20 Mo de mémoire, j'ai donc utilisé deux scripts R, comme suit:

D'abord un wrapper:

#!/usr/bin/Rscript --Vanilla --default-packages=utils

for(l in 1:length(fdir)) {

   for(k in 1:length(fds)) {
     system(paste("Rscript runConsensus.r", l, k))
   }
}

avec ce script, je contrôle fondamentalement ce que mon script principal fait runConsensus.r, et j'écris la réponse de données pour la sortie. Avec cela, chaque fois que l'encapsuleur appelle le script, il semble que le R soit rouvert et que la mémoire soit libérée.

J'espère que ça aide.

2
user1265067

Astuce pour traiter des objets nécessitant un calcul intermédiaire lourd: Lors de l'utilisation d'objets nécessitant beaucoup de calculs lourds et d'étapes intermédiaires, je trouve souvent utile d'écrire un bloc de code avec la fonction pour créer le object, puis un morceau de code séparé qui me donne l'option de générer et de sauvegarder l'objet en tant que fichier rmd ou de le charger en externe à partir d'un fichier rmd que j'avais déjà enregistré. Ceci est particulièrement facile à faire dans R Markdown en utilisant la structure de code-morceau suivante.

```{r Create OBJECT}

COMPLICATED.FUNCTION <- function(...) { Do heavy calculations needing lots of memory;
                                        Output OBJECT; }

```
```{r Generate or load OBJECT}

LOAD <- TRUE;
#NOTE: Set LOAD to TRUE if you want to load saved file
#NOTE: Set LOAD to FALSE if you want to generate and save

if(LOAD == TRUE) { OBJECT <- readRDS(file = 'MySavedObject.rds'); } else
                 { OBJECT <- COMPLICATED.FUNCTION(x, y, z);
                             saveRDS(file = 'MySavedObject.rds', object = OBJECT); }

```

Avec cette structure de code, tout ce que j'ai à faire est de changer LOAD selon que je souhaite générer et enregistrer l'objet ou le charger directement à partir d'un fichier enregistré existant. (Bien sûr, je dois le générer et le sauvegarder la première fois, mais j'ai ensuite la possibilité de le charger.) Le réglage de LOAD = TRUE contourne l'utilisation de ma fonction compliquée et évite tous les calculs lourds qu'il contient. Cette méthode nécessite toujours assez de mémoire pour stocker l'objet d'intérêt, mais vous évite de le calculer à chaque fois que vous exécutez votre code. Pour les objets qui nécessitent beaucoup de calculs lourds d'étapes intermédiaires (par exemple, pour les calculs impliquant des boucles sur de grands tableaux), cela peut économiser beaucoup de temps et de calcul.

2
Ben

Outre les techniques de gestion de la mémoire plus générales données dans les réponses ci-dessus, j'essaie toujours de réduire autant que possible la taille de mes objets. Par exemple, je travaille avec des matrices très volumineuses mais très rares, autrement dit des matrices où la plupart des valeurs sont nulles. En utilisant le package 'Matrix' (la capitalisation est importante), j'ai été en mesure de réduire la taille moyenne des objets de ~ 2 Go à ~ 200 Mo aussi simplement que:

my.matrix <- Matrix(my.matrix)

Le paquet Matrix comprend des formats de données qui peuvent être utilisés exactement comme une matrice ordinaire (inutile de changer d’autre code), mais sont capables de stocker beaucoup plus efficacement des données éparses, qu’elles soient chargées en mémoire ou sauvegardées sur disque.

De plus, les fichiers bruts que je reçois sont au format "long", où chaque point de données a des variables x, y, z, i. Beaucoup plus efficace pour transformer les données en un tableau de dimensions x * y * z avec uniquement la variable i.

Connaissez vos données et utilisez un peu de bon sens.

2
D Greenwood

Vous pouvez également obtenir des avantages en utilisant knitr et en insérant votre script dans Rmd Chuncks.

En général, je divise le code en plusieurs morceaux et je sélectionne celui qui enregistrera un point de contrôle dans le cache ou dans un fichier RDS.

Là-bas, vous pouvez définir un bloc à enregistrer en "cache", ou vous pouvez décider d'exécuter ou non un bloc particulier. De cette manière, lors d'une première exécution, vous ne pouvez traiter que la "partie 1", une autre exécution vous permettant de sélectionner uniquement la "partie 2", etc.

Exemple:

part1
```{r corpus, warning=FALSE, cache=TRUE, message=FALSE, eval=TRUE}
corpusTw <- corpus(Twitter)  # build the corpus
```
part2
```{r trigrams, warning=FALSE, cache=TRUE, message=FALSE, eval=FALSE}
dfmTw <- dfm(corpusTw, verbose=TRUE, removeTwitter=TRUE, ngrams=3)
```

Comme effet secondaire, cela pourrait également vous éviter quelques maux de tête en termes de reproductibilité :)

1
Matias Thayer

Basé sur les réponses de @ Dirk et de Tony, j'ai apporté une légère mise à jour. Le résultat était la sortie de [1] avant les jolies valeurs de taille. J'ai donc sorti le capture.output qui a résolu le problème:

.ls.objects <- function (pos = 1, pattern, order.by,
                     decreasing=FALSE, head=FALSE, n=5) {
napply <- function(names, fn) sapply(names, function(x)
    fn(get(x, pos = pos)))
names <- ls(pos = pos, pattern = pattern)
obj.class <- napply(names, function(x) as.character(class(x))[1])
obj.mode <- napply(names, mode)
obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
obj.prettysize <- napply(names, function(x) {
    format(utils::object.size(x),  units = "auto") })
obj.size <- napply(names, utils::object.size)

obj.dim <- t(napply(names, function(x)
    as.numeric(dim(x))[1:2]))
vec <- is.na(obj.dim)[, 1] & (obj.type != "function")
obj.dim[vec, 1] <- napply(names, length)[vec]
out <- data.frame(obj.type, obj.size, obj.prettysize, obj.dim)
names(out) <- c("Type", "Size", "PrettySize", "Rows", "Columns")
if (!missing(order.by))
    out <- out[order(out[[order.by]], decreasing=decreasing), ]
if (head)
    out <- head(out, n)

return(out)
}

# shorthand
lsos <- function(..., n=10) {
    .ls.objects(..., order.by="Size", decreasing=TRUE, head=TRUE, n=n)
}

lsos()
1
ilyas

J'essaie de limiter la quantité d'objets lorsque je travaille dans un projet plus important comportant de nombreuses étapes intermédiaires. Donc, au lieu de créer de nombreux objets uniques appelés

dataframe-> step1 -> step2 -> step3 -> result

raster-> multipliedRast -> meanRastF -> sqrtRast -> resultRast

Je travaille avec des objets temporaires que j'appelle temp.

dataframe -> temp -> temp -> temp -> result

Ce qui me laisse moins de fichiers intermédiaires et plus de vue d'ensemble.

raster  <- raster('file.tif')
temp <- raster * 10
temp <- mean(temp)
resultRast <- sqrt(temp)

Pour économiser davantage de mémoire, je peux simplement supprimer temp lorsqu'il n'est plus nécessaire.

rm(temp)

Si j'ai besoin de plusieurs fichiers intermédiaires, j'utilise temp1, temp2, temp3.

Pour tester, j'utilise test, test2, ...

0
mace

Fonctionnement

for (i in 1:10) 
    gc(reset = T)

de temps en temps, R aide également à libérer de la mémoire non utilisée mais restante libérée.

0
Marcelo Ventura