2013-05-10 20 views
6

Devo rilasciare una colonna da un data.frame contenente alcune centinaia di colonne.Idioma per rilasciare una singola colonna in un data.table

Con un data.frame, userei subset per farlo comodamente:

> dat <- data.table(data.frame(x=runif(10),y=rep(letters[1:5],2),z=runif(10)),key='y') 
> subset(dat,select=c(-z)) 
      x y 
1: 0.1969049 a 
2: 0.7916696 a 
3: 0.9095970 b 
4: 0.3529506 b 
5: 0.4923602 c 
6: 0.5993034 c 
7: 0.1559861 d 
8: 0.9929333 d 
9: 0.3980169 e 
10: 0.1921226 e 

Ovviamente questo funziona ancora, ma sembra non molto data.table -come idioma. Potrei costruire manualmente un elenco dei nomi delle colonne ho voluto mantenere, che sembra un po 'più data.table -come:

> dat[,list(x,y)] 
      x y 
1: 0.1969049 a 
2: 0.7916696 a 
3: 0.9095970 b 
4: 0.3529506 b 
5: 0.4923602 c 
6: 0.5993034 c 
7: 0.1559861 d 
8: 0.9929333 d 
9: 0.3980169 e 
10: 0.1921226 e 

Ma poi ho dovuto costruire un tale elenco, che è goffo.

È subset il modo corretto per rilasciare comodamente una o due colonne o provoca un calo di prestazioni? In caso contrario, qual è il modo migliore?

Modifica

Benchmark:

> dat <- data.table(data.frame(x=runif(10^7),y=rep(letters[1:10],10^6),z=runif(10^7)),key='y') 
> microbenchmark(subset(dat,select=c(-z)), dat[,list(x,y)]) 
Unit: milliseconds 
         expr  min  lq median  uq  max 
1   dat[, list(x, y)] 102.62826 167.86793 170.72847 199.89789 792.0207 
2 subset(dat, select = c(-z)) 33.26356 52.55311 53.53934 55.00347 180.8740 

Ma in realtà dove si può importare di più è per la memoria se subset copia l'intera data.table.

+0

Una domanda: qual è la vostra intenzione di eliminare questa colonna? Voglio dire cosa hai intenzione di fare con i dati risultanti.table? – Arun

+0

@Arun Il caso particolare che mi ha fatto chiedere, ho sbagliato il nome di una colonna durante la creazione con ': =' e volevo rilasciarlo. Ma viene fuori tutto il tempo che scaricare una colonna o due è a portata di mano. –

+1

Come spiega @mnel, se vuoi semplicemente rimuovere, puoi usare direttamente l'operatore ': =' e se vuoi eseguire calcoli senza questa colonna, puoi sempre usare '.SDcols'. Quindi, puoi evitare del tutto la soluzione 'subset' /' with = FALSE'. – Arun

risposta

9

Se si vogliono rimuovere la colonna utilizzare in modo permanente := NULL

dat[, z := NULL] 

Se avete le colonne a cadere come una stringa di caratteri utilizzare () per forzare la valutazione come una stringa di caratteri, non come il nome del personaggio.

toDrop <- c('z') 

dat[, (toDrop) := NULL] 

Se si vuole limitare la disponibilità delle colonne in .SD, è possibile passare l'argomento .SDcols

dat[,lapply(.SD, somefunction) , .SDcols = setdiff(names(dat),'z')] 

Tuttavia, data.table ispeziona i j argomenti e solo ottiene le colonne si utilizza alcun modo. Vedi FAQ 1,12

Quando si scrive X [Y, sum (foo * bar)], data.table ispeziona automaticamente l'espressione j per vedere le colonne che utilizza.

e non cercare di caricare tutti i dati per la .SD (a meno che non si dispone di .SD all'interno della vostra chiamata a j)


subset.data.table sta elaborando la chiamata e, infine, la valutazione dat[, c('x','y'), with=FALSE]

utilizzando := NULL dovrebbe essere fondamentalmente istantaneo, ma t fa eliminare definitivamente la colonna.

+2

mnel ha detto: "Usa'()' per forzare la valutazione come stringa di caratteri ".... Ho cercato di capire come farlo per settimane. Quel piccolo consiglio è degno del suo Q & A. –

1

Penso che questo sia quello che stai cercando.

dat[, !c("z"), with = FALSE] 

Ecco un punto di riferimento sugli enormi dati della modifica.

Unit: milliseconds 
         expr  min  lq median  uq  max neval 
    subset(dat, select = c(-z)) 53.37435 56.82514 61.81279 100.3458 339.1400 100 
      dat[, list(x, y)] 191.46678 354.39905 412.06421 451.3933 678.3981 100 
dat[, !c("z"), with = FALSE] 53.49184 57.31756 62.15506 112.7063 398.0107 100 
+0

'subset.data.table' è identico alla tua chiamata perché stanno facendo la stessa cosa vedi' getAnywhere ('subset.data.table') ' – mnel

+0

Preferisco questa sintassi a' sottoinsieme' a causa di [** questo post * *] (http://stackoverflow.com/questions/9860090/in-r-why-is-better-than-subset). Ho pensato che lo stesso argomento potesse essere esteso a 'data.table' – Arun

+0

@Arun Care per spiegare come funziona? Perché l'opzione 'with' deve essere' FALSE', ad esempio? –

Problemi correlati