Как удалить столбец по имени в 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из 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"]  

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

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

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

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

Как следствие, они действительно лучше всего подходят для интерактивного использования, когда можно, например, захотеть отобразить таблицу данных за вычетом любых столбцов с именами, содержащими подстроку "foo". Для целей программирования (или если вы действительно хотите удалить столбец (столбцы), df3а не из его копии), методы 1, 2a и 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()так, чтобы он возвращал целочисленный вектор.
Джош О'Брайен

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

6
Я не знал об этом data.tableни; добавлен FR # 1797 . Но метод 1 (почти) бесконечно быстрее других. Метод 1 удаляет столбец по ссылке без копирования вообще. Я сомневаюсь, что вы получите его выше 0,005 секунд для любого размера data.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)]

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

Очевидно, что он не так эффективен, потому что он обходит преимущества data.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

Для data.table назначение столбца в 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 нет запятой?

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


@Arun Я не могу вспомнить ни одной ситуации, data.framesкогда строки и столбцы будут переключаться. Это было бы нелогично.
duHaas

@Arun Я отметил вас, потому что ваш первый комментарий создавал впечатление, что вам приходилось звонить, DF[column,row]поэтому я просто хотел посмотреть, не было ли вообще случаев, когда это происходило.
duHaas

Обновлен ответ, чтобы удалить опечатку.
Contango
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.