Solte as colunas do frame de dados por nome

Eu tenho um número de colunas que gostaria de remover de um quadro de dados. Eu sei que podemos excluí-los individualmente usando algo como:

df$x <- NULL 

Mas eu estava esperando fazer isso com menos comandos.

Além disso, sei que posso descartar colunas usando indexação inteira como esta:

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

Mas estou preocupado que a posição relativa de minhas variables ​​possa mudar.

Dado o quão poderoso R é, eu percebi que poderia haver uma maneira melhor do que soltar cada coluna uma por uma.

Você pode usar uma lista simples de nomes:

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

Ou, alternativamente, você pode fazer uma lista dos que devem ser mantidos e se referir a eles pelo nome:

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

EDIT: Para aqueles ainda não familiarizados com o argumento de drop da function de indexação, se você quiser manter uma coluna como um quadro de dados, você faz:

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

drop=TRUE (ou não mencionar) irá diminuir dimensões desnecessárias e, portanto, retornar um vetor com os valores da coluna y .

Há também o comando subset , útil se você souber quais colunas deseja:

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

ATUALIZADO após comentário de @hadley: Para descartar colunas a, c você poderia fazer:

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

é provavelmente mais fácil, ou para múltiplas variables:

 within(df, rm(x, y)) 

Ou se você está lidando com data.table s (por Como você exclui uma coluna pelo nome em data.table? ):

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

ou para múltiplas variables

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

Na versão de desenvolvimento do data.table ( instruções de instalação ), with = FALSE não é mais necessário:

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

Você poderia usar %in% assim:

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

list (NULL) também funciona:

 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" 

Se você quiser remover as colunas por referência e evitar a cópia interna associada a data.frames , poderá usar o pacote data.table e a function :=

Você pode passar um nome de vetor de caractere para o lado esquerdo do operador := e NULL como o 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] 

Se você quiser predefinir os nomes como vetores de caractere fora da chamada para [ , agrupe o nome do object em () ou {} para forçar o LHS a ser avaliado no escopo de chamada e não como um nome dentro do escopo do 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. 

Você também pode usar set , o que evita a sobrecarga de [.data.table , e também funciona para 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) 

Existe uma estratégia potencialmente mais poderosa baseada no fato de que grep () retornará um vetor numérico. Se você tem uma longa lista de variables, como eu faço em um dos meus dados, algumas variables ​​que terminam em “.A” e outras que terminam em “.B” e você quer apenas aquelas que terminam em “.A” (ao longo com todas as variables ​​que não correspondem a nenhum padrão, faça o seguinte:

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

Para o caso em questão, usando o exemplo de Joris Meys, pode não ser tão compacto, mas seria:

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

Fora de interesse, isso sinaliza uma das estranhas inconsistências de syntax múltiplas do R. Por exemplo, dado um quadro de dados de duas colunas:

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

Isto dá um quadro de dados

 subset(df, select=-y) 

mas isso dá um vetor

 df[,-2] 

Isso tudo é explicado em ?[ Mas não é exatamente o comportamento esperado. Bem, pelo menos não para mim ...

Outra possibilidade:

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

ou

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

Outra resposta dplyr . Se suas variables ​​tiverem alguma estrutura de nomenclatura comum, você pode tentar o starts_with() . Por exemplo

 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 

Se você quiser descartar uma seqüência de variables ​​no quadro de dados, poderá usar : Por exemplo, se você quisesse eliminar var2 , var3 e todas as variables ​​intermediárias, você ficaria com 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 

Saída:

  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) 

Saída:

  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 

Aqui está uma maneira de dplyr com isso:

 #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() 

Eu gosto disso porque é intuitivo ler e entender sem annotations e robusto para as colunas que mudam de posição dentro do quadro de dados. Também segue o idioma vetorizado usando - para remover elementos.

Eu continuo pensando que deve haver uma linguagem melhor, mas para subtração de colunas pelo nome, eu costumo fazer o seguinte:

 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 

Existe uma function chamada dropNamed() no pacote BBmisc do Bernd Bischl que faz exatamente isso.

 BBmisc::dropNamed(df, "x") 

A vantagem é que evita repetir o argumento do quadro de dados e, portanto, é adequado para canalizar em magrittr (assim como as abordagens dplyr ):

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

Eu duvido que isso tenha muita atenção aqui, mas se você tem uma lista de colunas que você quer remover, e você quer fazer isso em uma cadeia dplyr , eu uso one_of() na cláusula select :

Aqui está um exemplo simples e reprodutível:

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

A documentação pode ser encontrada executando ?one_of or here:

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

Outra solução se você não quiser usar @ hadley’s acima: Se “COLUMN_NAME” for o nome da coluna que você deseja eliminar:

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

Além de select(-one_of(drop_col_names)) demonstrado em respostas anteriores, há algumas outras opções dplyr para descartar colunas usando select() que não envolvem a definição de todos os nomes de colunas específicos (usando os dados de amostra dweadr starwars para alguma variedade na coluna nomes):

 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 

Forneça o quadro de dados e uma sequência de nomes separados por vírgula para remover:

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

Uso :

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

insira a descrição da imagem aqui

Encontre o índice das colunas que você deseja eliminar usando which . Dê a esses índices um sinal negativo ( *-1 ). Em seguida, subconforme esses valores, o que os removerá do dataframe. Isto é um exemplo.

 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