web-dev-qa-db-fra.com

Sélection de colonnes dans le bloc de données R en fonction de celles * non * d'un vecteur

Je suis familier avec la possibilité d'extraire des colonnes d'une trame de données R (ou matrice) comme ceci:

df.2 <- df[, c("name1", "name2", "name3")]

Mais peut-on utiliser un ! Ou un autre outil pour sélectionner toutes sauf les colonnes listées?

Pour le fond, j'ai un bloc de données avec pas mal de vecteurs de colonnes et j'aimerais éviter:

  • Taper la majorité des noms quand je pouvais juste supprimer une minorité
  • En utilisant le df.2 <- df[, c(1,3,5)] beaucoup plus court parce que lorsque mon fichier .csv change, mon code va à diable puisque la numérotation n'est plus la même. Je suis nouveau dans R et je pense avoir appris la manière difficile de ne pas utiliser de vecteurs numériques pour les plus gros df qui pourraient changer.

J'ai essayé:

df.2 <- df[, !c("name1", "name2", "name3")]
df.2 <- df[, !=c("name1", "name2", "name3")]

Et juste au moment où je tapais ceci, j'ai découvert que cela fonctionne:

df.2 <- df[, !names(df) %in% c("name1", "name2", "name3")]

Y a-t-il un meilleur moyen que ce dernier?

38
Hendy

Une alternative à grep est which:

df.2 <- df[, -which(names(df) %in% c("name1", "name2", "name3"))]
27
harkmug

Vous pouvez effectuer un appel plus court qui est également plus généralisable avec grep-négatif:

df.2 <- df[, -grep("^name[1:3]$", names(df) )] 

Étant donné que grep renvoie des chiffres, vous pouvez utiliser l'indexation vectorielle négative pour supprimer les colonnes. Vous pouvez ajouter un nombre supplémentaire ou des motifs plus complexes.

11
42-

dplyr::select() a plusieurs options pour supprimer des colonnes spécifiques:

library(dplyr)

drop_columns <- c('cyl','disp','hp')
mtcars %>% 
  select(-one_of(drop_columns)) %>% 
  head(2)

              mpg drat    wt  qsec vs am gear carb
Mazda RX4      21  3.9 2.620 16.46  0  1    4    4
Mazda RX4 Wag  21  3.9 2.875 17.02  0  1    4    4

En annulant des noms de colonnes spécifiques, les éléments suivants suppriment la colonne "hp" et les colonnes de "qsec" à "gear":

mtcars %>% 
  select(-hp, -(qsec:gear)) %>% 
  head(2)

              mpg cyl disp drat    wt carb
Mazda RX4      21   6  160  3.9 2.620    4
Mazda RX4 Wag  21   6  160  3.9 2.875    4

Vous pouvez également annuler contains(), starts_with(), ends_with() ou matches():

mtcars %>% 
  select(-contains('t')) %>%
  select(-starts_with('a')) %>% 
  select(-ends_with('b')) %>% 
  select(-matches('^m.+g$')) %>% 
  head(2)

              cyl disp  hp  qsec vs gear
Mazda RX4       6  160 110 16.46  0    4
Mazda RX4 Wag   6  160 110 17.02  0    4
6
sbha

Vieux fil, mais voici une autre solution:

df.2 <- subset(df, select=-c(name1, name2, name3))

Cela a été publié dans un autre fil similaire (bien que je ne le trouve pas pour le moment). Devrait être un code durable dans la situation que vous décrivez, et est probablement plus facile à lire et à modifier que certaines des autres options.

2
mfloren

Vous pouvez créer une fonction personnalisée pour ce faire si vous l'utilisez pour votre propre usage pour manipuler des données. Je peux faire quelque chose comme ça:

rm.col <- function(df, ...) {
    x <- substitute(...())
    z <- Trim(unlist(lapply(x, function(y) as.character(y))))
    df[, !names(df) %in% z]
}

rm.col(mtcars, hp, mpg)

Le premier argument est le nom de la trame de données. le suivant ... sont les noms des colonnes que vous souhaitez supprimer.

2
Tyler Rinker

La façon la plus simple qui me vient à l'esprit:

filter_df <-df [ setdiff (noms (df), c ("nom1", "nom2")]

vous calculez essentiellement la différence entre la liste complète des noms de colonnes et le sous-ensemble que vous souhaitez filtrer (nom1 et nom2 ci-dessus).

0
Ahmed Osman