Eu tenho várias 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 esperava fazer isso com menos comandos.
Além disso, eu sei que eu poderia descartar colunas usando a indexação inteira como esta:
df <- df[ -c(1, 3:6, 12) ]
Mas estou preocupado que a posição relativa de minhas variáveis possa mudar.
Dado o quão poderoso é o R, achei que poderia haver uma maneira melhor do que soltar cada coluna uma a uma.
df#drop(var_name)
, e, em vez disso, precisamos fazer essas soluções complicadas?Respostas:
Você pode usar uma lista simples de nomes:
Ou, como alternativa, você pode fazer uma lista daqueles a serem mantidos e se referir a eles pelo nome:
EDIT: Para aqueles que ainda não estão familiarizados com o
drop
argumento da função de indexação, se desejar manter uma coluna como um quadro de dados, faça:drop=TRUE
(ou não mencioná-lo) eliminará dimensões desnecessárias e, portanto, retornará um vetor com os valores da colunay
.fonte
DF[,keeps]
vez deDF[keeps]
?Há também o
subset
comando, útil se você souber quais colunas deseja:ATUALIZADO após o comentário de @hadley: Para eliminar as colunas a, c, você pode:
fonte
subset
função R tivesse uma opção como "allbut = FALSE", que "inverte" a seleção quando definida como TRUE, ou seja, mantém todas as colunas, exceto as daselect
lista.df[c("a", "c")]
subset
comando, onde você não precisa colocar aspas nos nomes das colunas - acho que não me importo de digitar alguns caracteres extras apenas para evitar citar nomes :)subset
dentro de outras funções.é provavelmente mais fácil ou para várias variáveis:
Ou se você estiver lidando com
data.table
s (por Como você exclui uma coluna pelo nome em data.table? ):ou para várias variáveis
fonte
within(df, rm(x))
é de longe a solução mais limpa. Dado que essa é uma possibilidade, todas as outras respostas parecem desnecessariamente complicadas por uma ordem de magnitude.within(df, rm(x))
irá não funciona se existem colunas duplicadas nomeadosx
nodf
.df <- data.frame(x = 1, y = 2); names(df) <- c("x", "x"); within(df, rm(x))
retornadata.frame(x = 2, x = 2)
.within()
poderosa, mas que também usa o NSE. A nota na página de ajuda indica claramente que, para a programação, deve-se tomar cuidado suficiente.Você poderia usar
%in%
assim:fonte
DF[ , !(names(DF) %in% drops)]
identical(post_time_1, post_time_2) [1] TRUE
= Dlist (NULL) também funciona:
fonte
Se você deseja remover as colunas por referência e evitar a cópia interna associada
data.frames
, poderá usar odata.table
pacote e a função:=
Você pode passar os nomes de vetores de caracteres para o lado esquerdo do
:=
operador eNULL
como o RHS.Se você quiser predefinir os nomes como vetor de caracteres fora da chamada
[
, coloque o nome do objeto em()
ou{}
forçar o LHS a ser avaliado no escopo da chamada e não como um nome no escopo deDT
.Você também pode usar
set
, o que evita a sobrecarga de[.data.table
, e também funciona paradata.frames
!fonte
Existe uma estratégia potencialmente mais poderosa baseada no fato de que grep () retornará um vetor numérico. Se você possui uma lista longa de variáveis como eu em um dos meus conjuntos de dados, algumas variáveis terminam em ".A" e outras terminam em ".B" e você deseja apenas as que terminam em ".A" (junto com todas as variáveis que não correspondem a nenhum padrão, faça o seguinte:
Para o caso em questão, usando o exemplo de Joris Meys, pode não ser tão compacto, mas seria:
fonte
drops
, em primeiro lugar, comopaste0("^", drop_cols, "$")
, isso se torna muito mais agradável (leia-se: mais compacto) comsapply
:DF[ , -sapply(drops, grep, names(DF))]
Outra
dplyr
resposta. Se suas variáveis tiverem uma estrutura de nomenclatura comum, você pode tentarstarts_with()
. Por exemploSe você deseja soltar uma sequência de variáveis no quadro de dados, você pode usar
:
. Por exemplo, se você queria deixarvar2
,var3
e todas as variáveis no meio, você tinha acabado de ser deixado comvar1
:fonte
select()
, comocontains()
ormatches()
, que também aceita regex.Outra possibilidade:
ou
fonte
setdiff
é o ideal, especialmente no caso de um número muito grande de colunas.df <- df[ , -which(grepl('a|c', names(df)))]
Resultado:
Resultado:
fonte
Solução Dplyr
Duvido que isso receba muita atenção aqui em baixo, mas se você tiver uma lista de colunas que deseja remover e quiser fazê-lo em uma
dplyr
cadeia, utilizoone_of()
aselect
cláusula:Aqui está um exemplo simples e reproduzível:
A documentação pode ser encontrada em execução
?one_of
ou aqui:http://genomicsclass.github.io/book/pages/dplyr_tutorial.html
fonte
Fora de interesse, isso sinaliza uma das inconsistências múltiplas e estranhas de sintaxe de R. Por exemplo, dado um quadro de dados de duas colunas:
Isso fornece um quadro de dados
mas isso dá um vetor
Isso tudo é explicado,
?[
mas não é exatamente o comportamento esperado. Bem, pelo menos não para mim ...fonte
Aqui está uma
dplyr
maneira de fazer isso:Gosto disso porque é intuitivo ler e entender sem anotações e robusto para as colunas mudarem de posição dentro do quadro de dados. Também segue o idioma vetorizado usando
-
para remover elementos.fonte
%<>%
operador para substituir o objeto de entrada que pode ser simplificado paradf %<>% select(-col.to.drop.1, -col.to.drop.2, ..., -col.to.drop.6)
dplyr
pode ser mais fácil agrupá-las e colocar apenas um menos:df.cut <- df %>% select(-c(col.to.drop.1, col.to.drop.2, ..., col.to.drop.n))
Continuo pensando que deve haver um idioma melhor, mas, para subtração de colunas por nome, costumo fazer o seguinte:
fonte
df[,-match(c("e","f"),names(df))]
-
?Há uma função chamada
dropNamed()
noBBmisc
pacote de Bernd Bischl que faz exatamente isso.A vantagem é que evita repetir o argumento do quadro de dados e, portanto, é adequado para a inserção
magrittr
(assim como asdplyr
abordagens):fonte
Outra solução, se você não quiser usar o @ hadley's acima: Se "COLUMN_NAME" for o nome da coluna que você deseja excluir:
fonte
COLUMN_NAME
não estiver dentrodf
(verifique você mesmodf<-data.frame(a=1,b=2)
:). (3)df[,names(df) != "COLUMN_NAME"]
é mais simples e não sofre (2)Além das
select(-one_of(drop_col_names))
demonstradas nas respostas anteriores, existem algumas outrasdplyr
opções para descartar as colunasselect()
que não envolvem a definição de todos os nomes de colunas específicos (usando os dados de exemplo do dplyr starwars para alguma variedade nos nomes das colunas):Se você precisar soltar uma coluna que pode ou não existir no quadro de dados, aqui está uma ligeira reviravolta
select_if()
que, ao contrário de usarone_of()
, não emitirá umUnknown columns:
aviso se o nome da coluna não existir. Neste exemplo, 'bad_column' não é uma coluna no quadro de dados:fonte
Forneça o quadro de dados e uma sequência de nomes separados por vírgula para remover:
Uso :
fonte
Encontre o índice das colunas que você deseja soltar usando
which
. Atribua um sinal negativo a esses índices (*-1
). Em seguida, subconfigure esses valores, que os removerão do quadro de dados. Isto é um exemplo.fonte
Se você tem um grande
data.frame
e está com pouco uso de memória[
. . . . ourm
ewithin
para remover colunas de adata.frame
, comosubset
está atualmente (R 3.6.2), usando mais memória - ao lado da dica do manual para usarsubset
interativamente .fonte