Data.table içinde bir sütunu ada göre nasıl silebilirsiniz?


196

A "foo" adlı bir sütundan kurtulmak data.frameiçin şunu yapabilirim:

df <- df[-grep('foo', colnames(df))]

Ancak, bir kez nesneye dfdönüştürüldüğünde data.table, yalnızca bir sütunu kaldırmanın bir yolu yoktur.

Misal:

df <- data.frame(id = 1:100, foo = rnorm(100))
df2 <- df[-grep('foo', colnames(df))] # works
df3 <- data.table(df)
df3[-grep('foo', colnames(df3))] 

Ancak bir data.tablenesneye dönüştürüldüğünde , artık çalışmaz.


2
Bunun dtyerine data.table adını vermek daha net olurdu df3...
PatrickT

Yanıtlar:


284

Aşağıdakilerden herhangi biri foodata.table öğesinden sütunu kaldıracaktır df3:

# Method 1 (and preferred as it takes 0.00s even on a 20GB data.table)
df3[,foo:=NULL]

df3[, c("foo","bar"):=NULL]  # remove two columns

myVar = "foo"
df3[, (myVar):=NULL]   # lookup myVar contents

# Method 2a -- A safe idiom for excluding (possibly multiple)
# columns matching a regex
df3[, grep("^foo$", colnames(df3)):=NULL]

# Method 2b -- An alternative to 2a, also "safe" in the sense described below
df3[, which(grepl("^foo$", colnames(df3))):=NULL]

data.table ayrıca aşağıdaki sözdizimini de destekler:

## Method 3 (could then assign to df3, 
df3[, !"foo"]  

aslında sütunu kaldırmak isteyen olsaydı gerçi "foo"gelen df3(sadece bir görünümünü baskı aksine df3eksi hanesinde "foo") Gerçekten Yöntem 1 yerine kullanmak isterdim.

(Do not Eğer bir yöntem dayanarak kullanırsanız o grep()ya grepl(), sen ayarlamak gerekir pattern="^foo$"ziyade "foo"sizin gibi adlarla sütunları istemiyorsanız, "fool"ve "buffoon"(ihtiva yani o fooda eşleşti ve kaldırılacak) bir alt dize olarak.)

Daha az güvenli seçenekler, etkileşimli kullanım için iyi:

- Önümüzdeki iki deyimler de çalışacaktır eğer df3bir sütun eşleşmelerini içerir"foo" - ama eğer bu olmuyorsa bir olasılıkla-beklenmedik bir şekilde başarısız olur. Örneğin, var olmayan sütunu aramak için bunlardan herhangi birini kullanırsanız "bar", sıfır satırlı bir data.table elde edersiniz.

Sonuç olarak, örneğin bir veri görüntülemek isteyebilecek etkileşimli kullanım için en uygun olanlardır. Örneğin eksi alt dizeyi içeren adlara sahip herhangi bir sütun "foo". Programlama amacıyla (veya sütunları df3bir kopyadan ziyade gerçekten kaldırmak istiyorsanız), Yöntem 1, 2a ve 2b gerçekten en iyi seçeneklerdir.

# Method 4:
df3[, .SD, .SDcols = !patterns("^foo$")]

Son olarak, yaklaşımı kullanan yaklaşımlar vardır with=FALSE, ancak data.tableyavaş yavaş bu argümanı kullanmaktan uzaklaşmaktadır; burada göstererek gerçekten ihtiyacınız olması durumunda seçeneğin var olduğunu bilirsiniz:

# Method 5a (like Method 3)
df3[, !"foo", with=FALSE] 
# Method 5b (like Method 4)
df3[, !grep("^foo$", names(df3)), with=FALSE]
# Method 5b (another like Method 4)
df3[, !grepl("^foo$", names(df3)), with=FALSE]

2
OP ile ilgili -grepyorumuma bakın !grepl.
Joshua Ulrich

1
@JoshuaUlrich - İyi bir nokta. grepl()Initally denedim ve data.table sütunları mantıksal bir vektör tarafından dizin olamaz gibi, işe yaramadı. Ama şimdi bunun bir tamsayı vektörü döndürmesi için, onu grepl()sararak işe yarayabileceğini anlıyorum which().
Josh O'Brien

1
İle indeksleme hakkında bilmiyordum data.table, ama onu sarma whichakıllı!
Joshua Ulrich

6
Ben de bunu bilmiyordum data.table; FR # 1797 eklendi . Ancak, yöntem 1 (neredeyse) diğerlerinden sonsuz daha hızlıdır. Yöntem 1, hiçbir kopya olmadan sütun başvuru ile kaldırır. Herhangi bir boyut verisi için 0.005 saniyenin üzerine çıkacağınızdan şüpheliyim. Tablo. Buna karşılık, tablo RAM'in% 50'sine yakınsa, diğerleri silinecek olanlar dışında tümünü kopyaladıkları için hiç çalışmayabilir.
Matt Dowle

1
@ user3969377 Bir karakter değişkeninin içeriğine dayalı bir sütunu kaldırmak isterseniz, parantez içine almanız yeterlidir. Yani. df [, (afoo): = NULL]
Dean MacGregor

31

Döngülerdeki setek yükü önleyen bunun için de kullanabilirsiniz [.data.table:

dt <- data.table( a=letters, b=LETTERS, c=seq(26), d=letters, e=letters )
set( dt, j=c(1L,3L,5L), value=NULL )
> dt[1:5]
   b d
1: A a
2: B b
3: C c
4: D d
5: E e

Sütun adına göre yapmak istiyorsanız, which(colnames(dt) %in% c("a","c","e"))çalışmalısınız j.


2
Gelen data.tablesütun adıyla yapmak istiyorsanız 1.11.8, doğrudan yapabileceği rm.col = c("a","b")vedt[, (rm.col):=NULL]
Duccio A

20

Ben sadece veri çerçevesi tür şekilde yapmak:

DT$col = NULL

Hızlı çalışır ve gördüğüm kadarıyla sorun yaratmaz.

GÜNCELLEME: DT'niz çok büyükse, $<-operatörün kullanılması nesne kopyalamaya neden olacağından en iyi yöntem değildir . Çok daha iyi kullanın:

DT[, col:=NULL]

8

Bir veri tablosunda silinecek çok sayıda sütununuz olması ve tüm sütun adlarını yazmaktan kaçınmak istediğinizde çok basit bir seçenek #careadviced

dt <- dt[, -c(1,4,6,17,83,104)]

Bu, sütun sayısını sütun numarasına göre kaldıracaktır.

Açıkçası o kadar verimli değil çünkü verileri atlıyor. Tablo avantajları ancak 500.000 satırdan daha azıyla çalışıyorsanız, iyi çalışıyor


4

Senin dt sütun var varsayalım col1, col2, col3, col4, col5, coln.

Bir alt kümesini silmek için:

vx <- as.character(bquote(c(col1, col2, col3, coln)))[-1]
DT[, paste0(vx):=NULL]

bu yorum olmalı
Sachila Ranawaka

-2

Sütun adları kullanımınız için bir işlev verildiğinde # sütununu NULL olarak ayarlamak istediğinizde bir yol vardır :)

deleteColsFromDataTable <- function (train, toDeleteColNames) {

       for (myNm in toDeleteColNames)

       train <- train [,(myNm):=NULL]

       return (train)
}


-7

Bir data.table için, sütunu NULL değerine atamak sütunu kaldırır:

DT[,c("col1", "col1", "col2", "col2")] <- NULL
^
|---- Notice the extra comma if DT is a data.table

... ki buna eşdeğer:

DT$col1 <- NULL
DT$col2 <- NULL
DT$col3 <- NULL
DT$col4 <- NULL

Bir data.frame için eşdeğer:

DF[c("col1", "col1", "col2", "col2")] <- NULL
      ^
      |---- Notice the missing comma if DF is a data.frame

S. data.table sürümünde neden virgül var ve data.frame sürümünde virgül yok?

A. data.frames sütun listesi olarak saklandığından virgül atlayabilirsiniz. Bunu da ekleyebilirsiniz, ancak daha sonra bunları bir NULLs listesine atamanız gerekir DF[, c("col1", "col2", "col3")] <- list(NULL).


@Arun data.framesSatır ve sütunların değiştirileceği bir durum düşünemiyorum . Mantıksız olurdu.
duHaas

@Arun Sizi etiketledim, çünkü ilk yorumunuz arayabileceğiniz zamanlar gibi göründü, bu DF[column,row]yüzden gerçekten bunun gerçekleştiği herhangi bir örnek olup olmadığını görmek istedim.
duHaas

Yazım hatası kaldırmak için yanıt güncellendi.
Contango
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.