2013-05-10 14 views
6

Potrzebuję upuścić jedną kolumnę z data.frame zawierającego kilkaset kolumn.Idiom do upuszczania pojedynczej kolumny w data.table

Z data.frame, użyję subset to zrobić wygodnie:

> 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 

Oczywiście to nadal działa, ale wydaje się, że nie jest bardzo data.table -jak idiomu. Mogę ręcznie skonstruować listę nazw kolumn Chciałem zachować, co wydaje się trochę więcej data.table -jak:

> 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 

Ale to muszę skonstruować taką listę, która jest niezgrabne.

Czy jest to właściwy sposób wygodnego upuszczenia jednej lub dwóch kolumn, czy też powoduje to spadek wydajności? Jeśli nie, jaki jest lepszy sposób?

Edit

Benchmarki:

> 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 

Ale tak naprawdę, gdzie może ważniejsza jest dla pamięci jeśli subset kopii całego data.table.

+0

Jedno pytanie: jaki jest twój zamiar opuszczenia tej kolumny? Mam na myśli to, co zamierzasz zrobić z wynikowym plikiem data.table? – Arun

+0

@Arun Szczególny przypadek, który sprawił, że zapytałem, błędnie nazwałbym kolumnę podczas tworzenia z ': =' i chciałam ją upuścić. Ale pojawia się cały czas, że zrzucanie kolumny lub dwóch jest przydatne. –

+1

Jak wyjaśnia @mnel, jeśli chcesz po prostu usunąć, możesz bezpośrednio użyć operatora ': =' i jeśli chcesz wykonywać obliczenia bez tej kolumny, zawsze możesz użyć '.SDcols'. W ten sposób można całkowicie uniknąć rozwiązania 'subset' /' with = FALSE'. – Arun

Odpowiedz

9

Jeśli chcą usunąć kolumnę stale używać := NULL

dat[, z := NULL] 

Jeśli masz kolumn do spadku jako ciąg znaków używać () zmusić ocenę jako ciąg znaków, a nie jako nazwy postaci.

toDrop <- c('z') 

dat[, (toDrop) := NULL] 

Jeśli chcesz ograniczyć dostępność kolumn w .SD, możesz przekazać .SDcols argumentem

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

Jednak data.table kontroluje j argumenty i tylko dostaje kolumny używać w dowolny sposób. Zobacz nas 1,12

Kiedy piszesz X [Y, suma (foo * bar)], data.table automatycznie kontroluje ekspresję J, aby zobaczyć kolumny, które wykorzystuje.

i nie spróbować i załadować wszystkie dane do .SD (chyba że masz .SD w swoim powołaniu do j)


subset.data.table przetwarza połączenie i ostatecznie oceny dat[, c('x','y'), with=FALSE]

korzystania := NULL powinien być w zasadzie natychmiastowy, aveterer t trwale usuwa kolumnę.

+2

mnel powiedział: "Użyj"() ', aby wymusić ocenę jako ciąg znaków" .... Próbowałem dowiedzieć się, jak to zrobić przez kilka tygodni. Ta mała wskazówka jest warta własnych pytań i odpowiedzi. –

1

Myślę, że tego właśnie szukasz.

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

Oto wzorzec dla ogromnych danych z Twojej edycji.

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' jest identyczne z twoim wywołaniem, ponieważ robią to samo, zobacz' getAnywhere ('subset.data.table') ' – mnel

+0

Preferuję tę składnię do' podzbioru' z powodu [** tego posta * *] (http://stackoverflow.com/questions/9860090/in-r-why-is-better-than-subset). Zakładam, że ten sam argument może zostać rozszerzony na "data.table" – Arun

+0

@Arun Care, aby wyjaśnić, jak to działa? Dlaczego na przykład opcja 'with' musi mieć wartość' FALSE'? –

Powiązane problemy