Удаление столбцов фрейма данных по имени

У меня есть несколько столбцов, которые я хотел бы удалить из фрейма данных. Я знаю, что мы можем удалить их индивидуально, используя что-то вроде:

df$x <- NULL 

Но я надеялся сделать это с меньшим количеством команд.

Кроме того, я знаю, что я мог бы отбрасывать столбцы с использованием целочисленной индексации следующим образом:

 df <- df[ -c(1, 3:6, 12) ] 

Но я обеспокоен тем, что относительная позиция моих переменных может измениться.

Учитывая, насколько силен R, я решил, что может быть лучший способ, чем сбросить каждый столбец один за другим.

Вы можете использовать простой список имен:

 DF <- data.frame( x=1:10, y=10:1, z=rep(5,10), a=11:20 ) drops <- c("x","z") DF[ , !(names(DF) %in% drops)] 

Или, альтернативно, вы можете составить список тех, кто хранит их, и ссылаться на них по имени:

 keeps <- c("y", "a") DF[keeps] 

EDIT: для тех, кто еще не знаком с аргументом drop функции индексирования, если вы хотите сохранить один столбец в качестве фрейма данных, выполните следующие действия:

 keeps <- "y" DF[ , keeps, drop = FALSE] 

drop=TRUE (или не упоминает об этом) сбросит ненужные размеры и, следовательно, вернет вектор со значениями столбца y .

Также есть команда subset , полезная, если вы знаете, какие столбцы вы хотите:

 df <- data.frame(a = 1:10, b = 2:11, c = 3:12) df <- subset(df, select = c(a, c)) 

ОБНОВЛЕНО после комментария от @hadley: Чтобы удалить столбцы a, c, вы можете сделать:

 df <- subset(df, select = -c(a, c)) 
 within(df, rm(x)) 

вероятно, проще всего или для нескольких переменных:

 within(df, rm(x, y)) 

Или если вы имеете дело с data.table s (per) Как удалить столбец по имени в data.table? ):

 dt[, x := NULL] # deletes column x by reference instantly dt[, !"x", with=FALSE] # selects all but x into a new data.table 

или для нескольких переменных

 dt[, c("x","y") := NULL] dt[, !c("x", "y"), with=FALSE] 

В версии разработки data.table ( инструкции по установке ) with = FALSE больше не требуется:

 dt[ , !"x"] dt[ , !c("x", "y")] 

Вы можете использовать %in% следующим образом:

 df[, !(colnames(df) %in% c("x","bar","foo"))] 

список (NULL) также работает:

 dat <- mtcars colnames(dat) # [1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear" # [11] "carb" dat[,c("mpg","cyl","wt")] <- list(NULL) colnames(dat) # [1] "disp" "hp" "drat" "qsec" "vs" "am" "gear" "carb" 

Если вы хотите удалить столбцы по ссылке и избежать внутреннего копирования, связанного с data.frames тогда вы можете использовать пакет data.table и функцию :=

Вы можете передать имена векторных символов в левой части оператора := , а NULL как RHS.

 library(data.table) df <- data.frame(a=1:10, b=1:10, c=1:10, d=1:10) DT <- data.table(df) # or more simply DT <- data.table(a=1:10, b=1:10, c=1:10, d=1:10) # DT[, c('a','b') := NULL] 

Если вы хотите предопределить имена как вектор символов вне вызова [ , оберните имя объекта in () или {} чтобы заставить LHS оцениваться в области вызова не как имя в области DT .

 del <- c('a','b') DT <- data.table(a=1:10, b=1:10, c=1:10, d=1:10) DT[, (del) := NULL] DT <- <- data.table(a=1:10, b=1:10, c=1:10, d=1:10) DT[, {del} := NULL] # force or `c` would also work. 

Вы также можете использовать set , который позволяет избежать накладных расходов [.data.table , а также работает для data.frames !

 df <- data.frame(a=1:10, b=1:10, c=1:10, d=1:10) DT <- data.table(df) # drop `a` from df (no copying involved) set(df, j = 'a', value = NULL) # drop `b` from DT (no copying involved) set(DT, j = 'b', value = NULL) 

Существует потенциально более мощная страtagsя, основанная на том, что grep () вернет числовой вектор. Если у вас есть длинный список переменных, как в одном из моих наборов данных, некоторые переменные, которые заканчиваются на «.A» и другие, которые заканчиваются на «.B», и вам нужны только те, которые заканчиваются на «.A» (вдоль со всеми переменными, которые не соответствуют ни одному шаблону, выполните следующее:

 dfrm2 <- dfrm[ , -grep("\\.B$", names(dfrm)) ] 

Для рассматриваемого случая, используя пример Joris Meys, он может быть не таким компактным, но это будет:

 DF <- DF[, -grep( paste("^",drops,"$", sep="", collapse="|"), names(DF) )] 

Из интереса, это флаг одного из R странных множественных несоответствий синтаксиса. Например, для двухстолбцового кадра данных:

 df <- data.frame(x=1, y=2) 

Это дает структуру данных

 subset(df, select=-y) 

но это дает вектор

 df[,-2] 

Все это объясняется ?[ Но это не совсем ожидаемое поведение. Ну, по крайней мере, не мне ...

Другая возможность:

 df <- df[, setdiff(names(df), c("a", "c"))] 

или

 df <- df[, grep('^(a|c)$', names(df), invert=TRUE)] 

Еще dplyr ответ dplyr . Если ваши переменные имеют некоторую общую структуру именования, вы можете попробовать starts_with() . Например

 library(dplyr) df <- data.frame(var1 = rnorm(5), var2 = rnorm(5), var3 = rnorm (5), var4 = rnorm(5), char1 = rnorm(5), char2 = rnorm(5)) df # var2 char1 var4 var3 char2 var1 #1 -0.4629512 -0.3595079 -0.04763169 0.6398194 0.70996579 0.75879754 #2 0.5489027 0.1572841 -1.65313658 -1.3228020 -1.42785427 0.31168919 #3 -0.1707694 -0.9036500 0.47583030 -0.6636173 0.02116066 0.03983268 df1 <- df %>% select(-starts_with("char")) df1 # var2 var4 var3 var1 #1 -0.4629512 -0.04763169 0.6398194 0.75879754 #2 0.5489027 -1.65313658 -1.3228020 0.31168919 #3 -0.1707694 0.47583030 -0.6636173 0.03983268 

Если вы хотите отбросить последовательность переменных в фрейме данных, вы можете использовать : Например, если вы хотите удалить var2 , var3 и все переменные между ними, вы просто var1 с var1 :

 df2 <- df1 %>% select(-c(var2:var3) ) df2 # var1 #1 0.75879754 #2 0.31168919 #3 0.03983268 
 DF <- data.frame( x=1:10, y=10:1, z=rep(5,10), a=11:20 ) DF 

Вывод:

  xyza 1 1 10 5 11 2 2 9 5 12 3 3 8 5 13 4 4 7 5 14 5 5 6 5 15 6 6 5 5 16 7 7 4 5 17 8 8 3 5 18 9 9 2 5 19 10 10 1 5 20 

 DF[c("a","x")] <- list(NULL) 

Вывод:

  yz 1 10 5 2 9 5 3 8 5 4 7 5 5 6 5 6 5 5 7 4 5 8 3 5 9 2 5 10 1 5 

Вот способ dplyr :

 #df[ -c(1,3:6, 12) ] # original df.cut <- df %>% select(-col.to.drop.1, -col.to.drop.2, ..., -col.to.drop.6) # with dplyr::select() 

Мне это нравится, потому что интуитивно понятно читать и понимать без аннотаций и надежнее для столбцов, изменяющих позицию в кадре данных. Он также следует за векторизованной идиомой, использующей - для удаления элементов.

Я продолжаю думать, что должна быть лучшая идиома, но для вычитания столбцов по имени я имею тенденцию делать следующее:

 df <- data.frame(a=1:10, b=1:10, c=1:10, d=1:10) # return everything except a and c df <- df[,-match(c("a","c"),names(df))] df 

В dropNamed() Bernd Bischl есть функция, называемая dropNamed() , которая делает именно это.

 BBmisc::dropNamed(df, "x") 

Преимущество заключается в том, что он избегает повторения аргумента кадра данных и, следовательно, подходит для трубопроводов в magrittr (как и подходы dplyr ):

 df %>% BBmisc::dropNamed("x") 

Я сомневаюсь, что здесь будет много внимания, но если у вас есть список столбцов, которые вы хотите удалить, и вы хотите сделать это в цепочке dplyr я использую one_of() в предложении select :

Вот простой, воспроизводимый пример:

 undesired <- c('mpg', 'cyl', 'hp') mtcars %>% select(-one_of(undesired)) 

Документацию можно найти, выполнив ?one_of или здесь:

http://genomicsclass.github.io/book/pages/dplyr_tutorial.html

Другое решение, если вы не хотите использовать @ hasley выше: Если «COLUMN_NAME» – это имя столбца, который вы хотите удалить:

 df[,-which(names(df) == "COLUMN_NAME")] 

Помимо select(-one_of(drop_col_names)) продемонстрированного в более ранних ответах, есть пара других опций dplyr для dplyr столбцов с помощью select() которые не include в себя определение всех конкретных имен столбцов (с использованием данных выборки dplyr starwars для некоторого разнообразия в столбце имена):

 library(dplyr) starwars %>% select(-(name:mass)) %>% # the range of columns from 'name' to 'mass' select(-contains('color')) %>% # any column name that contains 'color' select(-starts_with('bi')) %>% # any column name that starts with 'bi' select(-ends_with('er')) %>% # any column name that ends with 'er' select(-matches('^f.+s$')) %>% # any column name matching the regex pattern select_if(~!is.list(.)) %>% # not by column name but by data type head(2) # A tibble: 2 x 2 homeworld species   1 Tatooine Human 2 Tatooine Droid 

Предоставьте кадр данных и строку разделенных запятыми имен для удаления:

 remove_features <- function(df, features) { rem_vec <- unlist(strsplit(features, ', ')) res <- df[,!(names(df) %in% rem_vec)] return(res) } 

Использование :

 remove_features(iris, "Sepal.Length, Petal.Width") 

введите описание изображения здесь

Найдите индекс столбцов, которые вы хотите удалить, используя. Дайте этим индексам отрицательный знак ( *-1 ). Затем подмножество этих значений, которое удалит их из фрейма данных. Это пример.

 DF <- data.frame(one=c('a','b'), two=c('c', 'd'), three=c('e', 'f'), four=c('g', 'h')) DF # one two three four #1 adfi #2 begj DF[which(names(DF) %in% c('two','three')) *-1] # one four #1 ag #2 bh 
  • Быстрое чтение очень больших таблиц в качестве данных
  • Какая самая большая R-gotcha, с которой вы столкнулись?
  • Как разбить фрейм данных?
  • Как вызвать объект с символьной переменной с тем же именем
  • Построение двух переменных в виде строк с использованием ggplot2 на одном графике
  • Поиск всех позиций для нескольких элементов в векторе
  • Есть ли встроенная функция для поиска режима?
  • Как создать последовательный индекс на основе переменной группировки в фрейме данных
  • Ошибка в : объект типа «закрытие» не является подмножеством
  • Динамически выбирать столбцы фрейма данных с помощью $ и вектора имен столбцов
  • Разница между скобками и двойной скобкой ] для доступа к элементам списка или кадра данных
  • Давайте будем гением компьютера.