Question 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 publications de Petr Pikal et David Hinds à la liste r-help en 2004] pour lister (et / ou trier) les plus grands objets et occasionnellement rm() certains d'entre eux. Mais de loin la solution la plus efficace était de fonctionner sous Linux 64 bits avec une mémoire suffisante.

D'autres trucs sympas 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)
}

444
2017-08-31 15:26


origine


Réponses:


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


175
2017-08-31 16:09



Je utilise l data.table paquet. Avec son := opérateur, vous pouvez:

  • Ajouter des colonnes par référence
  • Modifier les 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 même une fois.

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

Liens connexes :


147
2017-08-10 10:13



J'ai vu ça sur un post twitter et je pense que c'est une super fonction de Dirk! Suite à la réponse de JD Long, je le ferais 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 se traduit par quelque chose comme ceci:

                      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") })

97
2018-01-28 11:46



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 hacks pour la rendre présente avec un joli format 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
}

46
2018-03-09 15:59



Je fais un usage agressif du subset paramètre avec la sélection des seules variables requises lors du passage de données à la data= argument des fonctions de régression. Cela entraîne des erreurs si j'oublie d'ajouter des variables à la fois à la formule et au select= vecteur, mais il économise encore beaucoup de temps en raison de la copie réduite des objets et réduit de manière significative l’empreinte mémoire. Dire que j'ai 4 millions d'enregistrements avec 110 variables (et je le fais.) 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 mettant en contexte et la stratégie: le gdlab2 variable est un vecteur logique qui a été construit pour les sujets dans un ensemble de données qui avaient toutes les valeurs normales ou presque normales pour un tas de tests de laboratoire et HIVfinal était un vecteur de caractère qui résumait les tests préliminaires et de confirmation du VIH.


45
2017-12-05 18:15



C'est un bon truc.

Une autre suggestion consiste à utiliser des objets efficaces en mémoire chaque fois que cela est possible: par exemple, utilisez une matrice au lieu d’un fichier data.frame.

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


30
2017-08-31 19:08



J'aime bien la fonction améliorée des objets développée par Dirk. La plupart du temps, une sortie plus simple 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 triée par ordre alphabétique ou par taille, peut être limitée à un certain nombre d'objets et peut être triée par ordre croissant ou décroissant. En outre, je travaille souvent avec des données de 1 Go +, la fonction modifie donc les unités 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

30
2018-03-23 13:21



Malheureusement, je n'ai pas eu le temps de le tester intensivement mais voici un conseil de mémoire que je n'avais jamais vu auparavant. Pour moi, la mémoire nécessaire a été réduite de plus de 50%. Lorsque vous lisez des choses dans R avec, par exemple, read.csv, elles requièrent une certaine quantité de mémoire. Après cela, vous pouvez les enregistrer avec save("Destinationfile",list=ls()) La prochaine fois que vous ouvrez R, vous pouvez utiliser load("Destinationfile") Maintenant, l'utilisation de la mémoire peut avoir diminué. Ce serait bien si quelqu'un pouvait confirmer si cela produisait des résultats similaires avec un autre ensemble de données.


29
2017-10-07 09:37