Sumar repetidamente un conjunto específico de filas en el marco de datos
Frecuentes
Visto 467 veces
1
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!
1 Respuestas
3
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 eli
es undata.table
,DT[i,j]
evalúaj
para cada fila dei
. Llamamos a esto por sin por, o agrupar pori
.
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 r data.table or haz tu propia pregunta.
¿te estás quedando sin memoria? Además, ¿ha probado un backend paralelo diferente, digamos mclapply, en lugar de foreach? - ALiX