Удалить столбцы фрейма данных по имени - PullRequest
773 голосов
/ 05 января 2011

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

df$x <- NULL

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

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

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

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

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

Ответы [ 20 ]

820 голосов
/ 05 января 2011

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

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]

РЕДАКТИРОВАТЬ: Для тех, кто еще не знаком с аргументом drop функции индексации, если вы хотите сохранить один столбец в качестве фрейма данных, вы должны:

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

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

401 голосов
/ 05 января 2011

Также есть команда 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))
159 голосов
/ 29 сентября 2013
within(df, rm(x))

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

within(df, rm(x, y))

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

dt[, x := NULL]   # Deletes column x by reference instantly.

dt[, !"x"]   # Selects all but x into a new data.table.

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

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

dt[, !c("x", "y")]
102 голосов
/ 05 января 2011

Вы можете использовать %in% так:

df[, !(colnames(df) %in% c("x","bar","foo"))]
44 голосов
/ 12 февраля 2014

список (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"
37 голосов
/ 14 ноября 2012

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

Если вы хотите предварительно определить имена как символьный вектор вне вызова к [, оберните имяобъекта в () или {} для принудительной оценки 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)
37 голосов
/ 06 января 2011

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

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

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

DF <- DF[, -grep( paste("^",drops,"$", sep="", collapse="|"), names(DF) )]
24 голосов
/ 22 ноября 2014

Другой 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:

df2 <- df1 %>% select(-c(var2:var3) )  
df2
#        var1
#1 0.75879754
#2 0.31168919
#3 0.03983268
21 голосов
/ 20 июня 2014
DF <- data.frame(
  x=1:10,
  y=10:1,
  z=rep(5,10),
  a=11:20
)
DF

Выход:

    x  y z  a
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)

Выход:

        y z
    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
20 голосов
/ 02 мая 2013

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

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

Это дает фрейм данных

subset(df, select=-y)

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

df[,-2]

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

...