Sumar repetidamente un conjunto específico de filas en el marco de datos

Tengo lo siguiente:

Un entorno que funciona como un hash para filas en un marco de datos. Por ejemplo, el entorno "inc" tiene clave "hola" y get("hello", envir = inc) devolverá "fila1" "fila2" "fila50" donde estos son los nombres de las filas en un marco de datos. Después de seleccionar estas filas para una clave en el entorno, quiero realizar colSums en ellas.

El entorno tiene aproximadamente 400,000 400,000 entradas y quiero crear un nuevo marco de datos con 20 3 filas basadas en estas colSums. Tengo un código de trabajo que básicamente usa lapply/foreach para hacer esto y lo he usado en un pequeño subconjunto de datos... pero es INCREÍBLEMENTE lento. Como en... se ha estado ejecutando durante XNUMX minutos en XNUMX núcleos usando doMC y aún no ha terminado. Aquí está el código:

incCounts <- foreach(key = ls(inc)) %dopar% {
       transNames <- get(key, envir = inc)
       transCounts <- df[transNames, ]
       if ( ! is.null(dim(transCounts)) )
           transCounts <- colSums(transCounts)
       return(transCounts)
}
incCounts <- as.data.frame(t(simplify2array(incCounts)))

EDITAR: Aquí hay un ejemplo de lo que estoy tratando de hacer con un marco de datos y una tabla de datos:

library(data.table)
set.seed(20)
transEnv <- new.env(hash = TRUE)
assign("hash1", paste("trans", 2:4, sep = ""), envir = transEnv)
assign("hash2", paste("trans", c(1, 3), sep = ""), envir = transEnv)

df <- data.frame(matrix(rnorm(5 * 4), nrow = 4, ncol = 5))
rownames(df) <- paste("trans", 1:4, sep = "")
colSums(df[transEnv$hash1, ]) # what I want
       X1         X2         X3         X4         X5 
0.9476963 -3.2149230  0.7603257 -1.8494967  1.7569055

dt <- data.table(trans = rownames(df), df)
setkey(dt, trans)

# This isn't working as I expected... 
dt[transEnv$hash1, list(sum(X1), sum(X2), sum(X3), sum(X4), sum(X5))]

      trans         V1         V2         V3        V4         V5
[1,] trans2 -0.1444402 -1.4720633 -0.6135086  1.108451 1.24556891
[2,] trans3  0.7222297 -0.5961595 -0.2163115 -1.097342 0.08785472
[3,] trans4  0.3699069 -1.1467001  1.5901458 -1.860606 0.42348190

¡Cualquier ayuda será muy apreciada! ¡Gracias!

preguntado el 12 de junio de 12 a las 22:06

¿te estás quedando sin memoria? Además, ¿ha probado un backend paralelo diferente, digamos mclapply, en lugar de foreach? -

1 Respuestas

Puede ser apropiado para data.table. Vea wiki punto 5y esta respuesta. Si lo intentas, comienza con vignette('datatable-intro').

DT[,lapply(.SD,sum),by=grp]



Para responder a la edición, la sección correspondiente de ?data.table es:

Avanzado: la agregación de un subconjunto de grupos conocidos es particularmente eficiente cuando se pasan esos grupos en i. Cuando el i es un data.table, DT[i,j] evalúa j para cada fila de i. Llamamos a esto por sin por, o agrupar por i.

Entonces, en lugar de

dt[transEnv$hash1, list(sum(X1), sum(X2), sum(X3), sum(X4), sum(X5))]

intentar :

dt[transEnv$hash1, list(sum(X1),sum(X2),sum(X3),sum(X4),sum(X5)), mult="last"]

o,

dt[transEnv$hash1][, list(sum(X1), sum(X2), sum(X3), sum(X4), sum(X5))]

o,

dt[transEnv$hash1,lapply(.SD,sum),by="",.SDcols=names(dt)[-1]]

o,

dt[transEnv$hash1][,trans:=NULL][,sapply(.SD,sum)] 

contestado el 23 de mayo de 17 a las 11:05

Hola Mateo. Gracias por esto. Entonces, creé una tabla de datos y la clasifiqué por clave "transNames". Ahora, necesito un colSum sobre todas las columnas EXCEPTO 'transNames'. En realidad, no puedo usar "por" porque, por construcción, 'transNames' es único y tengo demasiadas combinaciones diferentes de filas para que sea factible usar "por". Simplemente quiero un acceso rápido a las filas de data.frame. He intentado hacer algo como DT[c("trans1", "trans2"), list(sum(V1), sum(V2))] pero esto solo devuelve el DT con las filas "trans1" y "trans2". ¿Sugerencias? ¡Gracias! - Harold

@Harold, no lo sigo, tengo miedo. ¿Puede proporcionar un pequeño conjunto de datos de ejemplo para ilustrar la entrada y la salida requerida, por favor? - matt dowle

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.