Trucos para gestionar la memoria disponible en una sesión de R
¿Qué trucos utiliza la gente para gestionar la memoria disponible de una sesión interactiva de R? Utilizo las siguientes funciones [basadas en publicaciones de Petr Pikal y David Hinds en la lista de ayuda de r en 2004] para enumerar (y/o ordenar) los objetos más grandes y, ocasionalmente, rm()
algunos de ellos. Pero, con diferencia, la solución más eficaz fue... ejecutarlo en Linux de 64 bits con amplia memoria.
¿Algún otro buen truco que la gente quiera compartir? Uno por publicación, por favor.
# 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)
}
Asegúrese de registrar su trabajo en un guión reproducible. De vez en cuando, vuelva a abrir R y luego source()
su script. Limpiarás todo lo que ya no uses y, como beneficio adicional, habrás probado tu código.
Yo uso el paquete data.table . Con su :=
operador podrás:
- Agregar columnas por referencia
- Modificar subconjuntos de columnas existentes por referencia y por grupo por referencia
- Eliminar columnas por referencia
Ninguna de estas operaciones copia el (potencialmente grande) data.table
en absoluto, ni siquiera una vez.
- La agregación también es particularmente rápida porque
data.table
utiliza mucha menos memoria de trabajo.
Enlaces relacionados :
- Noticias de data.table, presentación de London R, 2012
- ¿ Cuándo debo utilizar el
:=
operador en data.table?
¡Vi esto en una publicación de Twitter y creo que es una función increíble de Dirk! Siguiendo con la respuesta de JD Long , haría esto para una lectura fácil de usar:
# 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()
Lo que resulta en algo como lo siguiente:
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
NOTA: La parte principal que agregué fue (nuevamente, adaptada de la respuesta de JD):
obj.prettysize <- napply(names, function(x) {
print(object.size(x), units = "auto") })
Hago un uso agresivo del subset
parámetro seleccionando solo las variables requeridas cuando paso marcos de datos al data=
argumento de las funciones de regresión. Resulta en algunos errores si olvido agregar variables tanto a la fórmula como al select=
vector, pero aún así ahorra mucho tiempo debido a la disminución de la copia de objetos y reduce significativamente el uso de memoria. Digamos que tengo 4 millones de registros con 110 variables (y los tengo). Ejemplo:
# 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")
) )
A modo de establecer el contexto y la estrategia: la gdlab2
variable es un vector lógico que se construyó para sujetos en un conjunto de datos que tenía todos los valores normales o casi normales para un conjunto de pruebas de laboratorio y HIVfinal
era un vector de caracteres que resumía las pruebas preliminares y confirmatorias del VIH. .
Me encanta el script .ls.objects() de Dirk, pero seguí entrecerrando los ojos para contar caracteres en la columna de tamaño. Así que hice algunos trucos feos para que estuviera presente con un formato bonito para el tamaño:
.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
}