224 votes

Comment supprimer une colonne par son nom dans data.table ?

Pour se débarrasser d'une colonne nommée "foo" dans un fichier data.frame Je peux le faire :

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

Cependant, une fois que df est converti en un data.table il n'y a aucun moyen de supprimer une colonne.

Ejemplo:

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

Mais une fois qu'il est converti en un data.table cela ne fonctionne plus.

3 votes

Il aurait été plus clair de nommer le tableau data.table dt au lieu de df3 ...

327voto

Josh O'Brien Points 68397

L'un des éléments suivants supprimera la colonne foo à partir du tableau de données 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]

table.de.données prend également en charge la syntaxe suivante :

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

bien que si vous vouliez réellement supprimer la colonne "foo" de df3 (par opposition à la simple impression d'une vue de df3 colonne moins "foo" ), il est préférable d'utiliser la méthode 1.

(Notez que si vous utilisez une méthode s'appuyant sur grep() ou grepl() vous devez définir pattern="^foo$" plutôt que "foo" si vous ne voulez pas de colonnes portant des noms comme "fool" y "buffoon" (c'est-à-dire ceux qui contiennent foo comme une sous-chaîne) pour être également mis en correspondance et supprimé).

Options moins sûres, parfaites pour une utilisation interactive :

Les deux idiomes suivants fonctionneront également -- si df3 contient une colonne correspondant à "foo" -- mais échouera d'une manière probablement inattendue s'il ne le fait pas. Si, par exemple, vous utilisez l'un d'entre eux pour rechercher la colonne inexistante "bar" vous vous retrouverez avec un tableau data.table à zéro ligne.

Par conséquent, ils conviennent mieux à une utilisation interactive où l'on peut, par exemple, vouloir afficher un tableau de données sans les colonnes dont les noms contiennent la sous-chaîne "foo" . À des fins de programmation (ou si vous souhaitez réellement supprimer la ou les colonnes de l'application df3 plutôt qu'à partir d'une copie de celui-ci), les méthodes 1, 2a et 2b sont vraiment les meilleures options.

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

Enfin, il existe des approches utilisant with=FALSE mais data.table s'éloigne progressivement de l'utilisation de cet argument. Il est donc déconseillé de l'utiliser lorsque vous pouvez l'éviter ; il est indiqué ici pour que vous sachiez que l'option existe au cas où vous en auriez vraiment besoin :

# 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 votes

Voir mon commentaire au PO concernant -grep contre !grepl .

2 votes

@JoshuaUlrich -- Bon point. J'ai essayé grepl() initalement et cela n'a pas fonctionné, car les colonnes de data.table ne peuvent pas être indexées par un vecteur logique. Mais je réalise maintenant que grepl() peut fonctionner en l'entourant de which() de sorte qu'il renvoie un vecteur entier.

1 votes

Je ne savais pas qu'il fallait indexer avec data.table mais l'emballer dans which c'est intelligent !

32voto

Ari B. Friedman Points 24940

Vous pouvez également utiliser set pour cela, ce qui permet d'éviter les frais généraux de [.data.table en boucle :

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

Si vous voulez le faire par nom de colonne, which(colnames(dt) %in% c("a","c","e")) devrait fonctionner pour j .

3 votes

En data.table 1.11.8, si vous voulez le faire par nom de colonne, vous pouvez le faire directement rm.col = c("a","b") y dt[, (rm.col):=NULL]

21voto

msp Points 159

Je le fais simplement à la manière d'un cadre de données :

DT$col = NULL

Fonctionne rapidement et, d'après ce que j'ai pu voir, ne pose aucun problème.

MISE À JOUR : ce n'est pas la meilleure méthode si votre DT est très grand, car l'utilisation de la fonction $<- conduira à la copie d'objets. Il est donc préférable de l'utiliser :

DT[, col:=NULL]

-1voto

user3531326 Points 1

Voici une méthode pour définir un nombre de colonnes à NULL en fonction de leur nom. une fonction pour votre usage :)

deleteColsFromDataTable <- function (train, toDeleteColNames) {

       for (myNm in toDeleteColNames)

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

       return (train)
}

-6voto

Contango Points 7976

Pour une table data.table, l'attribution de la colonne à NULL la supprime :

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

... ce qui est l'équivalent de :

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

L'équivalent pour un data.frame est :

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

Q. Pourquoi y a-t-il une virgule dans la version pour data.table, et aucune virgule dans la version pour data.frame ?

A. Comme les data.frames sont stockés sous forme de liste de colonnes, vous pouvez sauter la virgule. Vous pouvez également l'ajouter, mais vous devrez alors les affecter à une liste de colonnes. NULL s, DF[, c("col1", "col2", "col3")] <- list(NULL) .

0 votes

@Arun Je ne peux pas penser à une situation avec laquelle data.frames où la ligne et les colonnes seraient permutées. Ce serait illogique.

0 votes

@Arun Je vous ai tagué parce que votre premier commentaire donnait l'impression qu'il y avait des moments où vous pouviez appeler DF[column,row] donc je voulais juste voir s'il y avait vraiment des cas où cela s'est produit.

0 votes

Mise à jour de la réponse pour supprimer une coquille.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X