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

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

Любое из следующего удалит столбец 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

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

Ответ 3

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

DT$col = NULL

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

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

DT[, col:=NULL]

Ответ 4

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

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

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

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

Ответ 5

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

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

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

Ответ 6

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

deleteColsFromDataTable < - function (train, toDeleteColNames) {

   for (myNm in toDeleteColNames)

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

   return (train)

}

Ответ 7

DT[,c:=NULL] # remove column c

Ответ 8

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