Extraire des colonnes spécifiques d'un bloc de données

366

J'ai un bloc de données R avec 6 colonnes et je veux créer un nouveau bloc de données qui ne comporte que trois des colonnes.

En supposant que mon trame de données est df, et je veux des colonnes d'extraction A, Bet E, c'est la seule commande que je peux comprendre:

 data.frame(df$A,df$B,df$E)

Existe-t-il une manière plus compacte de procéder?

Aren Cambre
la source

Réponses:

157

En utilisant le package dplyr , si votre data.frame est appelé df1:

library(dplyr)

df1 %>%
  select(A, B, E)

Cela peut également être écrit sans le %>%tube comme:

select(df1, A, B, E)
Sam Firke
la source
2
Compte tenu de l'évolution considérable du Tidyverse depuis la publication de ma question, je vous ai changé la réponse.
Aren Cambre
4
Étant donné le rythme effréné du changement dans le sens inverse, je déconseille d'utiliser ce modèle. Ceci s'ajoute à ma forte préférence contre le traitement des noms de colonnes comme s'il s'agissait de noms d'objets lors de l'écriture de code pour des fonctions, des packages ou des applications.
Joshua Ulrich
1
Cela fait plus de quatre ans que cette réponse a été soumise, et le schéma n'a pas changé. Les expressions canalisées peuvent être assez intuitives, c'est pourquoi elles sont attrayantes.
Aren Cambre
comment exécuter une autre commande sur ce sous-ensemble? Par exemple, je veux calculer le rowMean: "df1%>% rowMeans (select (A, B, E))" ne fonctionne pas.
Ben
Vous feriez chaîne ensemble un pipeline comme: df1 %>% select(A, B, E) %>% rowMeans(.). Consultez la documentation de la %>%pipe en tapant?magrittr::`%>%`
Sam Firke
448

Vous pouvez créer un sous-ensemble à l'aide d'un vecteur de noms de colonne. Je préfère fortement cette approche à celles qui traitent les noms de colonnes comme s'il s'agissait de noms d'objets (par exemple subset()), en particulier lors de la programmation dans des fonctions, des packages ou des applications.

# data for reproducible example
# (and to avoid confusion from trying to subset `stats::df`)
df <- setNames(data.frame(as.list(1:5)), LETTERS[1:5])
# subset
df[,c("A","B","E")]
Joshua Ulrich
la source
4
Cela donne l'erreur object of type 'closure' is not subsettable.
Aren Cambre
24
@ArenCambre: alors votre data.frame n'est pas vraiment nommé df. dfest également une fonction du package de statistiques.
Joshua Ulrich
2
@Cina: Parce que -"A"c'est une erreur de syntaxe. Et ?Extractdit, « , peut aussi être des nombres entiers négatifs, indiquant les éléments / tranches de quitter de la sélection. » ij...
Joshua Ulrich
7
Il y a un problème avec cette syntaxe parce que si on extrait une seule colonne R, retourne un vecteur au lieu d'une trame de données et cela pourrait être indésirable: > df[,c("A")] [1] 1. L'utilisation subsetn'a pas cet inconvénient.
David Dorchies
101

C'est le rôle de la subset()fonction:

> dat <- data.frame(A=c(1,2),B=c(3,4),C=c(5,6),D=c(7,7),E=c(8,8),F=c(9,9)) 
> subset(dat, select=c("A", "B"))
  A B
1 1 3
2 2 4
Stéphane Laurent
la source
Quand j'essaye ceci, avec mes données, j'obtiens l'erreur: "Erreur dans x [j]: type d'indice invalide 'liste'" Mais si c ("A", "B") n'est pas une liste, qu'est-ce que c'est ?
Rafael_Espericueta
@Rafael_Espericueta Difficile à deviner sans consulter votre code ... Mais c("A", "B")c'est un vecteur, pas une liste.
Stéphane Laurent
Il convertit la trame de données en liste.
Suat Atan PhD
78

Il y a deux choix évidents: celui de Joshua Ulrich df[,c("A","B","E")]ou

df[,c(1,2,5)]

un péché

> df <- data.frame(A=c(1,2),B=c(3,4),C=c(5,6),D=c(7,7),E=c(8,8),F=c(9,9)) 
> df
  A B C D E F
1 1 3 5 7 8 9
2 2 4 6 7 8 9
> df[,c(1,2,5)]
  A B E
1 1 3 8
2 2 4 8
> df[,c("A","B","E")]
  A B E
1 1 3 8
2 2 4 8
Henri
la source
16

Pour une raison quelconque seulement

df[, (names(df) %in% c("A","B","E"))]

travaillé pour moi. Toutes les syntaxes ci-dessus ont produit "des colonnes non définies sélectionnées".

so860
la source
15

Où df1 est votre trame de données d'origine:

df2 <- subset(df1, select = c(1, 2, 5))
Richard Ball
la source
7
Cela n'utilise pas dplyr. Il utilise base::subsetet est identique à la réponse de Stéphane Laurent, sauf que vous utilisez des numéros de colonne au lieu de noms de colonne.
Gregor Thomas
14

Vous pouvez également utiliser le sqldfpackage qui effectue des sélections sur les trames de données R comme:

df1 <- sqldf("select A, B, E from df")

Cela donne en sortie un bloc de données df1avec des colonnes: A, B, E.

Aman Burman
la source
2

Vous pouvez utiliser with:

with(df, data.frame(A, B, E))
Moody_Mudskipper
la source
1
df<- dplyr::select ( df,A,B,C)

En outre, vous pouvez attribuer un nom différent aux données nouvellement créées

data<- dplyr::select ( df,A,B,C)
Mohamed Rahouma
la source
0

[ et le sous-ensemble ne sont pas substituables:

[ renvoie un vecteur si une seule colonne est sélectionnée.

df = data.frame(a="a",b="b")    

identical(
  df[,c("a")], 
  subset(df,select="a")
) 

identical(
  df[,c("a","b")],  
  subset(df,select=c("a","b"))
)
fxi
la source
4
Pas si vous vous mettez drop=FALSE. Exemple:df[,c("a"),drop=F]
jusqu'au