Удаление столбцов фрейма данных по имени
У меня есть несколько столбцов, которые я хотел бы удалить из фрейма данных. Я знаю, что мы можем удалить их индивидуально, используя что-то вроде:
df$x <- NULL
Но я надеялся сделать это с меньшим количеством команд.
Кроме того, я знаю, что я мог бы отбрасывать столбцы с использованием целочисленной индексации следующим образом:
- Вычислить среднее по группе
- Как суммировать переменную по группе?
- Создайте пустой файл data.frame
- Изменение формы данных с широкоформатного формата
- Каковы различия между «=» и «<-» в R?
df <- df[ -c(1, 3:6, 12) ]
Но я обеспокоен тем, что относительная позиция моих переменных может измениться.
Учитывая, насколько силен R, я решил, что может быть лучший способ, чем сбросить каждый столбец один за другим.
- Почему суммировать или мутировать не работать с group_by при загрузке `plyr` после` dplyr`?
- Предупреждающее сообщение: В `...`: недопустимый факторный уровень, сгенерированный NA
- Передайте имя столбца data.frame в функцию
- Общие рекомендации по отладке в R
- Поиск всех повторяющихся строк, включая «элементы с меньшими индексами»,
- Что означает «Следующий объект замаскирован из« package: xxx »?
- Как удалить все пробелы из строки?
- Нумерация строк внутри групп в кадре данных
Вы можете использовать простой список имен:
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