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

166

Чтобы избавиться от столбца с именем "foo" в 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, это больше не работает.

  • 1
    Было бы яснее назвать data.table dt вместо df3 ...
Теги:
data.table

8 ответов

249
Лучший ответ

Любое из следующего удалит столбец foo из data.table 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", with=FALSE]  

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

(Обратите внимание: если вы используете метод, основанный на grep() или grepl(), вам нужно установить pattern="^foo$", а не "foo", если вам не нужны столбцы с именами типа "fool" и "buffoon" (т.е. те, которые содержат foo в качестве подстроки), также должны быть сопоставлены и удалены.)

Меньше безопасных опций, отлично подходит для интерактивного использования:

Следующие две идиомы также будут работать - , если df3 содержит столбец, соответствующий "foo", но, если это не так, произойдет непредвиденным образом. Если, например, вы используете любой из них для поиска несуществующего столбца "bar", вы получите таблицу данных с нулевой строкой.

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

# Method 4a:
df3[, -grep("^foo$", colnames(df3)), with=FALSE]

# Method 4b: 
df3[, !grepl("^foo$", colnames(df3)), with=FALSE]
  • 2
    Смотрите мой комментарий к ОП относительно -grep против !grepl .
  • 1
    @JoshuaUlrich - Хороший вопрос. Я попробовал grepl() изначально, и он не работал, так как столбцы data.table не могут быть проиндексированы логическим вектором. Но теперь я понимаю, что grepl() можно grepl() работать, обернув его с помощью which() , чтобы он возвращал целочисленный вектор.
Показать ещё 16 комментариев
30

Вы также можете использовать 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.

  • 0
    В data.table 1.11.8, если вы хотите сделать это по имени столбца, вы можете сделать непосредственно rm.col = c("a","b") и dt[, (rm.col):=NULL]
15

Я просто делаю это в виде кадра:

DT$col = NULL

Работает быстро и насколько я мог видеть, не вызывает никаких проблем.

UPDATE: не лучший метод, если ваш DT очень большой, поскольку использование оператора $<- приведет к копированию объекта. Поэтому лучше использовать:

DT[, col:=NULL]
3

Очень простая опция, если у вас есть много отдельных столбцов для удаления в таблице данных, и вы хотите избежать ввода всех имен столбцов #careadviced

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

Вместо этого удаляются столбцы на основе номера столбца.

Это явно не так эффективно, потому что он обходит преимущества data.table, но если вы работаете с менее чем 500 000 строк, он отлично работает

  • 0
    Плюс 1. И вскоре в CRAN v1.9.8 вам больше не нужна часть with=F
0

Предположим, что у вашего dt есть столбцы col1, col2, col3, col4, col5, coln.

Чтобы удалить подмножество из них:

vx <- as.character(bquote(c(col1, col2, col3, coln)))[-1]
DT[, paste0(vx):=NULL]
  • 0
    это должен быть комментарий
-1
DT[,c:=NULL] # remove column c
-3

Вот путь, когда вы хотите установить # столбцов в NULL с учетом их имен столбцов функция для вашего использования:)

deleteColsFromDataTable < - function (train, toDeleteColNames) {

   for (myNm in toDeleteColNames)

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

   return (train)

}

-6

Для таблицы данных. присвоение столбцу 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

Q. Почему в версии для таблицы data.table есть запятая и нет запятой в файле data.frame?

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

  • 0
    Что касается вашего вопроса - пожалуйста, прочитайте таблицу данных FAQ
  • 0
    @Arun Я не могу вспомнить ни одной ситуации с data.frames где строки и столбцы будут переключаться. Это было бы нелогично.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню