R dplyr: supprimer plusieurs colonnes

96

J'ai un dataframe et une liste de colonnes dans ce dataframe que j'aimerais supprimer. Prenons le irisjeu de données comme exemple. Je voudrais laisser tomber Sepal.Lengthet Sepal.Widthet utiliser uniquement les colonnes restantes. Comment faire cela en utilisant selectou à select_partir du dplyrpackage?

Voici ce que j'ai essayé jusqu'à présent:

drop.cols <- c('Sepal.Length', 'Sepal.Width')
iris %>% select(-drop.cols)

Erreur dans -drop.cols: argument non valide pour l'opérateur unaire

iris %>% select_(.dots = -drop.cols)

Erreur dans -drop.cols: argument non valide pour l'opérateur unaire

iris %>% select(!drop.cols)

Erreur dans! Drop.cols: type d'argument non valide

iris %>% select_(.dots = !drop.cols)

Erreur dans! Drop.cols: type d'argument non valide

J'ai l'impression de manquer quelque chose d'évident car cela semble être une opération assez utile qui devrait déjà exister. Sur Github, quelqu'un a publié un problème similaire et Hadley a déclaré utiliser une `` indexation négative ''. C'est ce que (je pense) j'ai essayé, mais en vain. Aucune suggestion?

Navaneethan Santhanam
la source

Réponses:

127

Consultez l'aide sur select_vars. Cela vous donne des idées supplémentaires sur la façon de travailler avec cela.

Dans ton cas:

iris %>% select(-one_of(drop.cols))
phiver
la source
Merci. Pour une raison quelconque, cela fonctionne sur iris, mais pas sur mon dataframe réel ( irisétait un exemple de jouet). Mon dataframe contient 4558 lignes et 147 colonnes. Le message d'erreur que j'ai reçu était Error in eval(x$expr, data, x$env) : variable names are limited to 10000 bytes. Une idée de pourquoi cela pourrait se produire?
Navaneethan Santhanam
1
Ah, on dirait que je faisais une erreur. J'ai accidentellement utilisé select_varsau lieu de select. Maintenant, cela fonctionne parfaitement!
Navaneethan Santhanam
5
Où sommes-nous censés trouver des fonctions intégrées comme one_of? Sauf si je manque quelque chose, il n'apparaît pas dans la documentation du paquet ( help(package='dplyr')).
geotheory
4
@geotheory, en fait one_of est documenté. voir help(one_of, package = "dplyr"). Au moins, il est dans la version 0.5.0 du package. Mais cela aide à lire les blogs publiés par Hadley lorsqu'il y a des mises à jour de l'un de ses packages. Et certaines fonctions sont documentées dans d'autres fonctions. Malheureusement, cela nécessite la lecture de toute la documentation, ce que je fais surtout lorsque je veux quelque chose qui n'est pas immédiatement évident ou possible avec la fonction.
phiver
10
Merci. Comment découvrez-vous ces fonctions en premier lieu, en termes de documentation?
geotheory le
67

Essayez aussi

## Notice the lack of quotes
iris %>% select (-c(Sepal.Length, Sepal.Width))
Miguel Rayon Gonzalez
la source
5
Génial! Vraiment utile lorsque nous devons supprimer des colonnes en copiant-collant les noms de la console.
Pablo Casas
37

Au-delà, select(-one_of(drop.cols))il existe quelques autres options pour supprimer des colonnes select()qui n'impliquent pas de définir tous les noms de colonnes spécifiques (en utilisant les exemples de données dplyr starwars pour une plus grande variété de noms de colonnes):

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
  <chr>     <chr>  
1 Tatooine  Human  
2 Tatooine  Droid 
sbha
la source
Est select_if(~!is.list(.))équivalent à select_if(is.list(.))?
Jasha
3
Dans ce cas, ~c'est le raccourci purrr pour définir une fonction anonyme, ce n'est pas un autre symbole pour non. Par exemple, ces deux signifient la même chose function(x) {!is.list(x)}et ~!is.list(.). pensez ~à un raccourci pour function(.).
SlyFox
8

Soyez prudent avec la select()fonction, car elle est utilisée à la fois dans les paquets dplyr et MASS, donc si MASS est chargé, select () peut ne pas fonctionner correctement. Pour savoir quels packages sont chargés, saisissez-les sessionInfo()et recherchez-les dans la section "autres packages attachés:". S'il est chargé, tapez detach( "package:MASS", unload = TRUE )et votre select()fonction devrait fonctionner à nouveau.

Durand Sinclair
la source
12
vous pouvez également accéder à la fonction directement dans l'espace de noms du package comme tel dplyr::select().
Triamus
2
J'ai trop souvent rencontré ce problème. Maintenant, je définis généralement une nouvelle fonction en haut de mon script dselect <- dplyr::select().
filups21
5

Nous pouvons essayer

iris %>% 
      select_(.dots= setdiff(names(.),drop.cols))
Akrun
la source
Merci @akrun, cela a parfaitement fonctionné. Cependant, étant donné la dplyrcapacité du battage médiatique environnant à rendre les tâches d'analyse de base faciles à lire et à écrire, je suis déçu que la solution réelle ressemble à une solution de contournement.
Navaneethan Santhanam
@NavaneethanSanthanam En fait, l' one_ofautre solution est la voie à suivre. Je l'ai oublié.
akrun
3

Une autre façon consiste à muter les colonnes indésirables en NULL, cela évite les parenthèses incorporées:

head(iris,2) %>% mutate_at(drop.cols, ~NULL)
#   Petal.Length Petal.Width Species
# 1          1.4         0.2  setosa
# 2          1.4         0.2  setosa
Moody_Mudskipper
la source
Cela ne donne pas non plus d'avertissement si une colonne n'est pas là.
skoz
3

Si vous avez un caractère spécial dans les noms de colonne, cela fonctionne selectou select_peut ne pas fonctionner comme prévu. Cette propriété dplyrd'utilisation ".". Pour faire référence à l'ensemble de données dans la question, la ligne suivante peut être utilisée pour résoudre ce problème:

drop.cols <- c('Sepal.Length', 'Sepal.Width')
  iris %>% .[,setdiff(names(.),drop.cols)]
dineshram mattapalli
la source
Les réponses au code uniquement sont déconseillées. Veuillez expliquer comment la réponse fonctionne et en quoi elle diffère des réponses déjà présentes.
Ralf Stubner
Je vous remercie!! Aucune des autres solutions ci-dessus n'a fonctionné pour cette raison exacte.
Marty999
0

Tu peux essayer

iris %>% select(-!!drop.cols)
Lefty
la source