J'ai un certain nombre de colonnes que je voudrais supprimer d'un bloc de données. Je sais que nous pouvons les supprimer individuellement en utilisant quelque chose comme:
df$x <- NULL
Mais j'espérais le faire avec moins de commandes.
De plus, je sais que je pourrais supprimer des colonnes en utilisant l'indexation entière comme ceci:
df <- df[ -c(1, 3:6, 12) ]
Mais je crains que la position relative de mes variables ne change.
Étant donné la puissance de R, j'ai pensé qu'il pourrait y avoir un meilleur moyen que de supprimer chaque colonne une par une.
df#drop(var_name)
, et à la place, nous devons faire ces contournements compliqués?Réponses:
Vous pouvez utiliser une simple liste de noms:
Ou, alternativement, vous pouvez faire une liste de ceux à conserver et vous y référer par nom:
EDIT: Pour ceux qui ne connaissent pas encore l'
drop
argument de la fonction d'indexation, si vous souhaitez conserver une colonne comme trame de données, vous devez:drop=TRUE
(ou ne pas le mentionner) supprimera les dimensions inutiles, et donc retournera un vecteur avec les valeurs de la colonney
.la source
DF[,keeps]
au lieu deDF[keeps]
?Il y a aussi la
subset
commande, utile si vous savez quelles colonnes vous voulez:MISE À JOUR après commentaire de @hadley: Pour supprimer les colonnes a, c, vous pouvez faire:
la source
subset
fonction R ait une option comme "allbut = FALSE", qui "inverse" la sélection lorsqu'elle est définie sur TRUE, c'est-à-dire qui conserve toutes les colonnes sauf celles de laselect
liste.df[c("a", "c")]
subset
commande où vous n'avez pas besoin de mettre des guillemets autour des noms de colonnes - Je suppose que cela ne me dérange pas de taper quelques caractères supplémentaires juste pour éviter de citer des noms :)subset
intérieur d'autres fonctions.est probablement le plus simple, ou pour plusieurs variables:
Ou si vous avez affaire à
data.table
s (par Comment supprimer une colonne par nom dans data.table? ):ou pour plusieurs variables
la source
within(df, rm(x))
est de loin la solution la plus propre. Étant donné que c'est une possibilité, toutes les autres réponses semblent inutilement compliquées par un ordre de grandeur.within(df, rm(x))
cela ne fonctionnera pas s'il y a des colonnes en double nomméesx
dansdf
.df <- data.frame(x = 1, y = 2); names(df) <- c("x", "x"); within(df, rm(x))
retournedata.frame(x = 2, x = 2)
.within()
puissante mais qui utilise également NSE. La note sur la page d'aide indique clairement que pour la programmation, des soins suffisants doivent être utilisés.Vous pouvez utiliser
%in%
comme ceci:la source
DF[ , !(names(DF) %in% drops)]
identical(post_time_1, post_time_2) [1] TRUE
= Dlist (NULL) fonctionne également:
la source
Si vous souhaitez supprimer les colonnes par référence et éviter la copie interne associée,
data.frames
vous pouvez utiliser ledata.table
package et la fonction:=
Vous pouvez passer un nom de vecteur de caractères sur le côté gauche de l'
:=
opérateur etNULL
comme RHS.Si vous souhaitez prédéfinir les noms en tant que vecteur de caractères en dehors de l'appel à
[
, encapsulez le nom de l'objet dans()
ou{}
pour forcer le LHS à être évalué dans la portée appelante et non en tant que nom dans la portée deDT
.Vous pouvez également utiliser
set
, ce qui évite la surcharge de[.data.table
, et travaille aussi pourdata.frames
!la source
Il existe une stratégie potentiellement plus puissante basée sur le fait que grep () retournera un vecteur numérique. Si vous avez une longue liste de variables comme je le fais dans l'un de mes ensembles de données, certaines variables qui se terminent par ".A" et d'autres qui se terminent par ".B" et vous ne voulez que celles qui se terminent par ".A" (avec avec toutes les variables qui ne correspondent à aucun modèle, procédez comme suit:
Dans le cas présent, en utilisant l'exemple de Joris Meys, ce n'est peut-être pas aussi compact, mais ce serait:
la source
drops
en premier lieu commepaste0("^", drop_cols, "$")
, cela devient beaucoup plus agréable (lire: plus compact) avecsapply
:DF[ , -sapply(drops, grep, names(DF))]
Une autre
dplyr
réponse. Si vos variables ont une structure de dénomination commune, vous pouvez essayerstarts_with()
. Par exempleSi vous souhaitez supprimer une séquence de variables dans le bloc de données, vous pouvez utiliser
:
. Par exemple, si vous souhaitez supprimervar2
,var3
et toutes les variables entre les deux, il vous restera simplementvar1
:la source
select()
, commecontains()
oumatches()
, qui accepte également regex.Une autre possibilité:
ou
la source
setdiff
est optimale surtout dans le cas d'un très grand nombre de colonnes.df <- df[ , -which(grepl('a|c', names(df)))]
Production:
Production:
la source
Solution Dplyr
Je doute que cela obtienne beaucoup d'attention ici, mais si vous avez une liste de colonnes que vous souhaitez supprimer et que vous souhaitez le faire dans une
dplyr
chaîne que j'utiliseone_of()
dans laselect
clause:Voici un exemple simple et reproductible:
La documentation peut être trouvée en exécutant
?one_of
ou ici:http://genomicsclass.github.io/book/pages/dplyr_tutorial.html
la source
Par intérêt, cela signale l'une des étranges incohérences de syntaxe multiples de R. Par exemple, étant donné un bloc de données à deux colonnes:
Cela donne une trame de données
mais cela donne un vecteur
Tout cela est expliqué dans
?[
mais ce n'est pas exactement le comportement attendu. Enfin du moins pas pour moi ...la source
Voici une
dplyr
façon de procéder:J'aime cela car il est intuitif de lire et de comprendre sans annotation et robuste aux colonnes changeant de position dans le bloc de données. Il suit également l'idiome vectorisé utilisé
-
pour supprimer des éléments.la source
%<>%
opérateur pour remplacer l'objet d'entrée, il pourrait être simplifiédf %<>% select(-col.to.drop.1, -col.to.drop.2, ..., -col.to.drop.6)
dplyr
, il pourrait être plus facile de les regrouper et de mettre un seul moins:df.cut <- df %>% select(-c(col.to.drop.1, col.to.drop.2, ..., col.to.drop.n))
Je continue de penser qu'il doit y avoir un meilleur idiome, mais pour la soustraction de colonnes par nom, j'ai tendance à faire ce qui suit:
la source
df[,-match(c("e","f"),names(df))]
-
?Il y a une fonction appelée
dropNamed()
dans leBBmisc
package de Bernd Bischl qui fait exactement cela.L'avantage est qu'il évite de répéter l'argument de trame de données et convient donc à la canalisation
magrittr
(tout comme lesdplyr
approches):la source
Autre solution si vous ne souhaitez pas utiliser @ hadley ci-dessus: Si "COLUMN_NAME" est le nom de la colonne que vous souhaitez supprimer:
la source
COLUMN_NAME
n'est pas le casdf
(vérifiez vous-même:)df<-data.frame(a=1,b=2)
. (3)df[,names(df) != "COLUMN_NAME"]
est plus simple et ne souffre pas de (2)Au-delà de ce qui a été
select(-one_of(drop_col_names))
démontré dans les réponses précédentes, il existe quelques autresdplyr
options pour supprimer des colonnesselect()
qui n'impliquent pas la définition de tous les noms de colonnes spécifiques (en utilisant les exemples de données dplyr starwars pour une certaine variété de noms de colonnes):Si vous devez supprimer une colonne qui peut ou peut ne pas exister dans le bloc de données, voici une légère torsion
select_if()
qui, contrairement à l'utilisationone_of()
, ne lancera pas d'Unknown columns:
avertissement si le nom de la colonne n'existe pas. Dans cet exemple, 'bad_column' n'est pas une colonne dans le bloc de données:la source
Fournissez le bloc de données et une chaîne de noms séparés par des virgules à supprimer:
Utilisation :
la source
Recherchez l'index des colonnes que vous souhaitez supprimer à l'aide de
which
. Donnez à ces index un signe négatif (*-1
). Sous-ensemble ensuite sur ces valeurs, ce qui les supprimera de la trame de données. Ceci est un exemple.la source
Si vous avez une grande
data.frame
mémoire et que vous utilisez peu de mémoire[
. . . . ourm
etwithin
pour supprimer les colonnes d'undata.frame
, commesubset
c'est actuellement le cas (R 3.6.2) en utilisant plus de mémoire - à côté de l'indice du manuel à utiliser de manièresubset
interactive .la source