Як видалити стовпець за іменем у data.table?


196

Щоб позбутися стовпця з назвою "foo" в a data.frame, я можу:

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

Однак, як тільки dfперетворюється на data.tableоб’єкт, немає можливості просто видалити стовпчик.

Приклад:

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))] 

Але як тільки він перетворюється на data.tableоб’єкт, це більше не працює.


2
Було б зрозуміліше назвати таблицю data.table dtзамість df3...
PatrickT

Відповіді:


284

Будь-яке з наведеного нижче видалить стовпець fooіз таблиці даних 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 також підтримує такий синтаксис:

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

хоча, якщо ви насправді хотіли видалити стовпчик "foo"із df3(на відміну від простого друку подання df3мінус стовпця "foo"), ви б дійсно захотіли скористатися Методом 1.

(Зверніть увагу, що якщо ви використовуєте метод, який покладається на grep()або grepl(), вам потрібно встановити, pattern="^foo$"а не "foo", якщо ви не хочете, щоб стовпці з іменами на зразок "fool"і "buffoon"(тобто такими, що містять fooяк підрядку) також були зіставлені та видалені.)

Менш безпечні варіанти, штрафи для інтерактивного використання:

Наступні дві ідіоми також працюватимуть - якщо вони df3містять відповідність стовпців"foo" - але, напевно, будуть невдалі, якщо цього немає. Якщо, наприклад, ви використовуєте будь-який з них для пошуку неіснуючого стовпця "bar", ви отримаєте нульовий рядок data.table.

Як наслідок, вони дійсно найкраще підходять для інтерактивного використання, де можна, наприклад, бажати відобразити таблицю даних. мінус будь-які стовпці з іменами, що містять підрядку "foo". Для цілей програмування (або якщо ви хочете фактично видалити стовпець (-и), df3а не з його копії), Методи 1, 2а та 2b - це справді найкращі варіанти.

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

Нарешті, існують підходи, які використовують with=FALSE, хоча data.tableпоступово відходить від використання цього аргументу, тому тепер не відволікається, де можна цього уникнути; показуючи тут, щоб ви знали, що варіант існує у випадку, якщо він вам справді потрібен:

# 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
Дивіться мій коментар до ОП стосовно -grepпорівняно !grepl.
Джошуа Ульріх

1
@JoshuaUlrich - Добрий момент. Я спробував grepl()ініціально, і це не спрацювало, оскільки стовпці data.table не можуть бути індексовані логічним вектором. Але тепер я розумію, що grepl()можна змусити працювати, обернувши його which(), щоб він повернув цілий вектор.
Josh O'Brien

1
Я не знав, що про індексацію за допомогою data.table, але обгортати це whichрозумно!
Джошуа Ульріх

6
Я про це не знав data.table; додано FR # 1797 . Але метод 1 (майже) нескінченно швидший, ніж інші. Спосіб 1 видаляє стовпчик шляхом посилання без копії взагалі. Сумніваюсь, ви отримаєте це вище 0,005 секунди для будь-якого розміру даних.table. На відміну від цього, інші можуть взагалі не працювати, якщо таблиця становить близько 50% оперативної пам’яті, оскільки вони копіюють все, окрім видалення.
Метт Даул

1
@ user3969377 Якщо ви хочете видалити стовпчик на основі вмісту змінної символу, ви просто загорнете його в дужки. Тобто df [, (afoo): = NULL]
Дін МакГрегор

31

Ви також можете використовувати setдля цього, що дозволяє уникнути накладних витрат [.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

Якщо ви хочете зробити це за назвою стовпця, which(colnames(dt) %in% c("a","c","e"))слід працювати j.


2
У data.table1.11.8, якщо ви хочете зробити це за назвою стовпця, ви можете зробити це безпосередньо rm.col = c("a","b")іdt[, (rm.col):=NULL]
Duccio A

20

Я просто роблю це в кадрі даних таким чином:

DT$col = NULL

Працює швидко і, наскільки я міг бачити, не викликає проблем.

ОНОВЛЕННЯ: не найкращий метод, якщо ваш DT дуже великий, оскільки використання $<-оператора призведе до копіювання об'єктів. Тож краще скористайтеся:

DT[, col:=NULL]

8

Дуже простий варіант, якщо у таблиці даних є багато окремих стовпців, які потрібно видалити, і ви хочете уникати введення всіх назв стовпців #careadviced

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

Це замість цього видалить стовпці на основі номера стовпця.

Це, очевидно, не настільки ефективно, оскільки він обходить переваги даних.table, але якщо ви працюєте з менш ніж 500 000 рядків, це прекрасно працює


4

Припустимо , що ваш дт має стовпці col1, col2, col3, col4, col5, coln.

Щоб видалити підмножину з них:

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

це слід прокоментувати
Sachila Ranawaka

-2

Ось спосіб, коли ви хочете встановити # стовпців на NULL, враховуючи назви їх стовпців функцію для вашого використання :)

deleteColsFromDataTable <- function (train, toDeleteColNames) {

       for (myNm in toDeleteColNames)

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

       return (train)
}


-7

Для таблиці даних.призначення стовпця NULL видаляє його:

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

... що еквівалентно:

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

Еквівалент для data.frame:

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

З. Чому в версії для data.table є кома, а у версії для data.frame немає кома?

A. Оскільки кадри data.frames зберігаються як список стовпців, ви можете пропустити кому. Ви також можете додати його, тим НЕ менш , то вам потрібно буде призначити їх в список NULLз, DF[, c("col1", "col2", "col3")] <- list(NULL).


@Arun Я не можу придумати жодної ситуації з data.framesпереключенням рядка та стовпців. Це було б нелогічно.
duHaas

@Arun Я позначив вас, тому що ваш перший коментар показав, що бували випадки, коли ви можете зателефонувати, DF[column,row]тому я просто хотів дізнатися, чи справді є випадки, коли це сталося.
duHaas

Оновлено відповідь про видалення друку.
Контанго
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.