2012-04-11 8 views
6

Usando una tabla de datos, ¿cuál sería la manera más rápida de "barrer" una estadística en una selección de columnas?data.tables y función de barrido

A partir de (versiones considerablemente mayor de DT)

p <- 3 
DT <- data.table(id=c("A","B","C"),x1=c(10,20,30),x2=c(20,30,10)) 
DT.totals <- DT[, list(id,total = x1+x2) ] 

me gustaría llegar al siguiente resultado data.table mediante la indexación de las columnas de destino (2: p) con el fin de omitir la clave:

id x1 x2 
[1,] A 0.33 0.67 
[2,] B 0.40 0.60 
[3,] C 0.75 0.25 

Respuesta

4

creo que algo parecido a lo siguiente (que utiliza la función relativamente nueva set()) será más rápida:

DT <- data.table(id = c("A","B","C"), x1 = c(10,20,30), x2 = c(20,30,10)) 
total <- DT[ , x1 + x2] 

rr <- seq_len(nrow(DT)) 
for(j in 2:3) set(DT, rr, j, DT[[j]]/total) 
DT 
#  id  x1  x2 
# [1,] A 0.3333333 0.6666667 
# [2,] B 0.4000000 0.6000000 
# [3,] C 0.7500000 0.2500000 

Fwiw, llama a set() tiene la siguiente forma:

# set(x, i, j, value), where: 
#  x is a data.table 
#  i contains row indices 
#  j contains column indices 
#  value is the value to be assigned into the specified cells 

Mi sospecha acerca de la velocidad relativa de este, en comparación con otras soluciones, se basa en este pasaje de data.table's NEWS file, en el apartado de cambios en la versión 1.8.0:

o New function set(DT,i,j,value) allows fast assignment to elements 
    of DT. Similar to := but avoids the overhead of [.data.table, so is 
    much faster inside a loop. Less flexible than :=, but as flexible 
    as matrix subassignment. Similar in spirit to setnames(), setcolorder(), 
    setkey() and setattr(); i.e., assigns by reference with no copy at all. 

     M = matrix(1,nrow=100000,ncol=100) 
     DF = as.data.frame(M) 
     DT = as.data.table(M) 
     system.time(for (i in 1:1000) DF[i,1L] <- i) # 591.000s 
     system.time(for (i in 1:1000) DT[i,V1:=i])  # 1.158s 
     system.time(for (i in 1:1000) M[i,1L] <- i) # 0.016s 
     system.time(for (i in 1:1000) set(DT,i,1L,i)) # 0.027s 
+0

Gracias por la respuesta. Me actualicé a data.table 1.8.0 y ejecuté con éxito el código de prueba anterior. Obtengo una advertencia elaborada (no encajaré aquí) sobre la coerción para duplicar cuando tanto el numerador como los denominadores son columnas enteras de data.tables. Editaré la pregunta a ese efecto. –

+0

Estoy teniendo un momento difícil con ediciones de hoy: sin alimentación de línea. De todos modos, aquí está el código: para (j en 2: p) { conjunto (dt, allrows, j, dt [[j]]/denom [[2]]) } y para ambos dt y denom, columnas 2 a p son enteros. La advertencia que recibo es –

+0

"Mensaje de advertencia: En conjunto (dt, allrows, j, dt [[j]]/denom [[2]]): Coaccionó 'doble' RHS a 'entero' para que coincida con el tipo de columna ; puede tener precisión truncada. Cambie la columna de destino a "doble" primero (creando una nueva longitud de vector "doble" 16863 (nrows de toda la tabla) y asigne eso, es decir, columna "reemplazar") o fuerce RHS a "entero" '(por ejemplo, 1L, NA_ [real | integer] _, as. *, etc.) para aclarar su intención y para la velocidad. O bien, configure el tipo de columna correctamente al principio cuando cree la tabla y apéguese a ella, por favor. –

Cuestiones relacionadas