ticks - r plot title




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

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

df$x <- NULL

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

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

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

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

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


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

BBmisc::dropNamed(df, "x")

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

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

Вот способ 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(
  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 .


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

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

или же

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

Если вы хотите удалить столбцы по ссылке и избежать внутреннего копирования, связанного с 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)

Еще 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

Найдите индекс столбцов, которые вы хотите удалить, используя. Дайте этим индексам отрицательный знак ( *-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   a   d     f    i
#2   b   e     g    j

DF[which(names(DF) %in% c('two','three')) *-1]
#  one four
#1   a    g
#2   b    h

Помимо select(-one_of(drop_col_names)) продемонстрированного в более ранних ответах, есть пара других опций dplyr для dplyr столбцов с помощью select() которые не включают в себя определение всех конкретных имен столбцов (с использованием данных выборки 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
  <chr>     <chr>  
1 Tatooine  Human  
2 Tatooine  Droid 

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

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

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

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

Также есть команда 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))

список (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"

Решение Dplyr

Я сомневаюсь, что здесь будет много внимания, но если у вас есть список столбцов, которые вы хотите удалить, и вы хотите сделать это в цепочке 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


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")]




r-faq