R — Data.table — удаление столбцов по ссылке с использованием отрицательной позиции

#r #data.table

#r #data.table

Вопрос:

Мне нравится способ удаления столбцов в таблице данных:

 library(data.table)
data <- mtcars
setDT(data)
data[, 1:3 := NULL]
 

Удаление столбцов по позиции не всегда является лучшим решением, но часто оно удобно. Я ожидал, что это сработает (удалите все столбцы, которые не находятся в позиции 1: 3):

 data[, !1:3 := NULL]
 

Но это возвращает эту ошибку:

 Error in `[.data.table`(data, , `:=`(!1:3, NULL)) : 
  LHS of := isn't column names ('character') or positions ('integer' or 'numeric')
 

Проверка данных таким же образом работает:

 data[, !1:3]
    hp drat    wt  qsec vs am gear carb
 1: 110 3.90 2.620 16.46  0  1    4    4
 2: 110 3.90 2.875 17.02  0  1    4    4
 3:  93 3.85 2.320 18.61  1  1    4    1
 4: 110 3.08 3.215 19.44  1  0    3    1
...
 

Я могу сделать что-то вроде:

 delCol <- colnames(data)
delCol <- tail(delCol, -3)
data[, c(delCol) := NULL]
 

Но это менее удобно. Есть ли лучший способ?

Комментарии:

1. я что-то упустил. что вам мешает data = data[, 1:3] ?

2. ! обычно применяется к логическим векторам. 1: 3 не логично.

3. StupidWolf: Вы правы. Я так увлекся удалением по ссылке, что проигнорировал самый очевидный ответ. Я все еще думаю, что было бы неплохо отказаться от! 1: 3, хотя 🙂

4. Существует ожидающий PR, который позволил бы dt[, names(.SD) := NULL, .SDcols = !1:3] . github.com/Rdatatable/data.table/pull/4163 . Аналогично, если вас интересует только выбор столбцов, а не удаление, вы можете сделать as.data.table(iris)[, !1:3, with = FALSE]

5. Я некоторое время наблюдал за этим PR. Спасибо за вашу работу над этой функцией убийцы @Cole.

Ответ №1:

Конечно, вы можете выбрать только первые три столбца, как предложено в комментариях. Но если вы действительно хотите удалить по ссылке, вы можете рассмотреть возможность работы с colnames :

 library(data.table)
data <- mtcars
setDT(data)

data[, colnames(data)[-c(1:3)] := NULL]

head(data)
#>     mpg cyl disp
#> 1: 21.0   6  160
#> 2: 21.0   6  160
#> 3: 22.8   4  108
#> 4: 21.4   6  258
#> 5: 18.7   8  360
#> 6: 18.1   6  225
 

В качестве альтернативы, что-то вроде этого будет работать:

 data[, setdiff(1:ncol(data), 1:3) := NULL]