credo che qualcosa di simile a quanto segue (che utilizza la relativamente nuova funzione set()
) sarà più veloce:
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, chiama set()
assume la seguente 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
mio sospetto circa la velocità relativa di questo, rispetto ad altre soluzioni, si basa su questo passaggio da data.table's NEWS file, nella sezione dedicata ai cambiamenti nella versione 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
Grazie per la risposta. Ho aggiornato a data.table 1.8.0 e ho eseguito correttamente il codice di test sopra. Ricevo un avvertimento elaborato (che non si adatta qui) sulla coercizione da raddoppiare quando sia il numeratore che i denominatori sono colonne intere di data.tables. Modificherò la domanda in questo senso. –
Oggi mi trovo in difficoltà con le modifiche: nessun feed di riga. Ad ogni modo, ecco il codice: per (j in 2: p) { set (dt, allrows, j, dt [[j]]/denom [[2]]) } e per entrambi dt e denom, colonne 2 a p sono numeri interi. L'avvertimento che ricevo è –
"Messaggio di avviso: In set (dt, allrows, j, dt [[j]]/denom [[2]]): Costretto 'double' RHS a 'numero intero' per abbinare il tipo di colonna ; può avere una precisione troncata. O cambiare prima la colonna di destinazione in "doppio" (creando una nuova lunghezza "double" del vettore 16863 (nrows di tutta la tabella) e assegnare quella colonna, ad esempio "replace"), o forzare RHS a "intero" '(ad es. 1L, NA_ [reale | intero] _, come. *, ecc.) per rendere chiaro e veloce il tuo intento oppure impostare il tipo di colonna correttamente in primo piano quando crei la tabella e attenersi ad essa, per favore. " –