Como você exclui uma coluna pelo nome em data.table?


195

Para se livrar de uma coluna chamada "foo" em a data.frame, eu posso fazer:

df <- df[-grep('foo', colnames(df))]

No entanto, uma vez dfconvertido em um data.tableobjeto, não há como remover apenas uma coluna.

Exemplo:

df <- data.frame(id = 1:100, foo = rnorm(100))
df2 <- df[-grep('foo', colnames(df))] # works
df3 <- data.table(df)
df3[-grep('foo', colnames(df3))] 

Mas uma vez convertido em um data.tableobjeto, isso não funciona mais.


2
Teria sido mais claro para nomear o data.table dtem vez de df3...
PatrickT

Respostas:


283

Qualquer uma das seguintes fooopções removerá a coluna da data.table df3:

# Method 1 (and preferred as it takes 0.00s even on a 20GB data.table)
df3[,foo:=NULL]

df3[, c("foo","bar"):=NULL]  # remove two columns

myVar = "foo"
df3[, (myVar):=NULL]   # lookup myVar contents

# Method 2a -- A safe idiom for excluding (possibly multiple)
# columns matching a regex
df3[, grep("^foo$", colnames(df3)):=NULL]

# Method 2b -- An alternative to 2a, also "safe" in the sense described below
df3[, which(grepl("^foo$", colnames(df3))):=NULL]

data.table também suporta a seguinte sintaxe:

## Method 3 (could then assign to df3, 
df3[, !"foo"]  

no entanto, se você realmente deseja remover a coluna "foo"de df3(em vez de apenas imprimir uma exibição da df3coluna de menos "foo"), realmente deseja usar o Método 1.

(Observe que, se você usar um método baseado em grep()ou grepl(), precisará definir, em pattern="^foo$"vez de "foo", se não desejar que colunas com nomes como "fool"e "buffoon"(ou seja, aquelas que contenham foocomo substring) sejam correspondidas e removidas.)

Opções menos seguras, ótimas para uso interativo:

Os próximos dois idiomas também funcionarão - se df3contiverem uma correspondência de coluna"foo" - mas falharão de uma maneira provavelmente inesperada se não existirem. Se, por exemplo, você usar algum deles para procurar a coluna inexistente "bar", você terminará com uma tabela de dados com linha zero.

Como conseqüência, eles são realmente mais adequados para uso interativo, onde se pode, por exemplo, querer exibir uma tabela de dados menos quaisquer colunas com nomes contendo a substring "foo". Para fins de programação (ou se você realmente deseja remover as colunas df3de uma cópia), os Métodos 1, 2a e 2b são realmente as melhores opções.

# Method 4:
df3[, .SD, .SDcols = !patterns("^foo$")]

Por fim, existem abordagens usando with=FALSE, embora data.tableesteja gradualmente se afastando do uso desse argumento, por isso agora é desencorajado onde você pode evitá-lo; mostrando aqui para que você saiba que a opção existe, caso você realmente precise:

# Method 5a (like Method 3)
df3[, !"foo", with=FALSE] 
# Method 5b (like Method 4)
df3[, !grep("^foo$", names(df3)), with=FALSE]
# Method 5b (another like Method 4)
df3[, !grepl("^foo$", names(df3)), with=FALSE]

2
Veja meu comentário ao OP sobre -grepversus !grepl.
1937 Joshua Ulrich

1
@JoshuaUlrich - Bom ponto. Tentei grepl()inicialmente e não funcionou, pois as colunas data.table não podem ser indexadas por um vetor lógico. Mas agora percebo que isso grepl()pode ser feito ao envolvê-lo which(), para que ele retorne um vetor inteiro.
Josh O'Brien

1
Eu não sabia disso sobre indexação data.table, mas envolvê-la whiché inteligente!
Joshua Ulrich

6
Eu também não sabia disso data.table; adicionado FR # 1797 . Mas, o método 1 é (quase) infinitamente mais rápido que os outros. O método 1 remove a coluna por referência sem nenhuma cópia. Duvido que você obtenha acima de 0,005 segundos para qualquer tamanho data.table. Por outro lado, os outros podem não funcionar se a tabela estiver perto de 50% da RAM, porque eles copiam todos, exceto o que deseja excluir.
quer

1
@ user3969377 se você deseja remover uma coluna com base no conteúdo de uma variável de caractere, basta colocá-la entre parênteses. Ou seja. df [, (afoo): = NULL]
Dean MacGregor

31

Você também pode usar setisso, o que evita a sobrecarga de [.data.tableloops:

dt <- data.table( a=letters, b=LETTERS, c=seq(26), d=letters, e=letters )
set( dt, j=c(1L,3L,5L), value=NULL )
> dt[1:5]
   b d
1: A a
2: B b
3: C c
4: D d
5: E e

Se você deseja fazê-lo pelo nome da coluna, which(colnames(dt) %in% c("a","c","e"))deve trabalhar para j.


2
Na data.tableversão 1.11.8, se você quiser fazê-lo pelo nome da coluna, poderá fazê-lo diretamente rm.col = c("a","b")e #dt[, (rm.col):=NULL]
Duccio A

20

Simplesmente faço isso no quadro de dados:

DT$col = NULL

Funciona rápido e, tanto quanto pude ver, não causa problemas.

UPDATE: não é o melhor método se a sua TD for muito grande, pois o uso do $<-operador levará à cópia de objetos. Então, use melhor:

DT[, col:=NULL]

8

Opção muito simples, caso você tenha muitas colunas individuais para excluir em uma tabela de dados e evite digitar todos os nomes de coluna #careadviced

dt <- dt[, -c(1,4,6,17,83,104)]

Isso removerá as colunas com base no número da coluna.

Obviamente, não é tão eficiente porque ignora as vantagens da data.table, mas se você estiver trabalhando com menos do que 500.000 linhas, ele funciona bem


4

Suponha que seu dt tem colunas col1, col2, col3, col4, col5, coln.

Para excluir um subconjunto deles:

vx <- as.character(bquote(c(col1, col2, col3, coln)))[-1]
DT[, paste0(vx):=NULL]

esta deve ser comentário
Sachila Ranawaka

-2

Aqui está uma maneira de definir um número de colunas como NULL, considerando os nomes de suas colunas uma função para seu uso :)

deleteColsFromDataTable <- function (train, toDeleteColNames) {

       for (myNm in toDeleteColNames)

       train <- train [,(myNm):=NULL]

       return (train)
}


-7

Para uma tabela de dados, atribuir a coluna a NULL a remove:

DT[,c("col1", "col1", "col2", "col2")] <- NULL
^
|---- Notice the extra comma if DT is a data.table

... que é o equivalente a:

DT$col1 <- NULL
DT$col2 <- NULL
DT$col3 <- NULL
DT$col4 <- NULL

O equivalente para um data.frame é:

DF[c("col1", "col1", "col2", "col2")] <- NULL
      ^
      |---- Notice the missing comma if DF is a data.frame

P. por que há uma vírgula na versão para data.table e nenhuma vírgula na versão para data.frame?

A. Como data.frames são armazenados como uma lista de colunas, você pode pular a vírgula. Você também pode adicioná-lo, mas precisará atribuí-los a uma lista de NULLs DF[, c("col1", "col2", "col3")] <- list(NULL),.


@ Arun Não consigo pensar em nenhuma situação em data.framesque a linha e as colunas seriam trocadas. Isso seria ilógico.
duHaas

@Arun eu te etiquetei porque seu primeiro comentário fez parecer que houve momentos em que você poderia ligar, DF[column,row]então eu só queria ver se realmente havia algum caso em que isso aconteceu.
duHaas

Atualizado a resposta para remover um erro de digitação.
Contango
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.