J'ai un grand ensemble de données et je voudrais lire des colonnes spécifiques ou supprimer toutes les autres.
data <- read.dta("file.dta")
Je sélectionne les colonnes qui ne m'intéressent pas:
var.out <- names(data)[!names(data) %in% c("iden", "name", "x_serv", "m_serv")]
et que j'aimerais faire quelque chose comme:
for(i in 1:length(var.out)) {
paste("data$", var.out[i], sep="") <- NULL
}
pour supprimer toutes les colonnes indésirables. Est-ce la solution optimale?
subset(data, select=c(...))
aide dans mon cas pour la suppression de vars. la question était cependant principalement sur lapaste("data$",var.out[i],sep="")
partie pour accéder aux colonnes d'intérêt à l'intérieur de la boucle. comment puis-je coller ou composer en quelque sorte un nom de colonne? Merci à tous pour votre attention et votre aideRéponses:
Vous devez utiliser l'indexation ou la
subset
fonction. Par exemple :Ensuite, vous pouvez utiliser la
which
fonction et l'-
opérateur dans l'indexation des colonnes:Ou, beaucoup plus simple, utilisez l'
select
argument de lasubset
fonction: vous pouvez alors utiliser l'-
opérateur directement sur un vecteur de noms de colonnes, et vous pouvez même omettre les guillemets autour des noms!Notez que vous pouvez également sélectionner les colonnes de votre choix au lieu de supprimer les autres:
la source
select
argument de lasubset
fonction a parfaitement fonctionné! Merci juba!which
n'est pas nécessaire, voir la réponse d'Ista. Mais le sous-ensemble avec-
est sympa! Je ne savais pas ça!subset
semble bon, mais la façon dont il supprime silencieusement les valeurs manquantes me semble assez dangereuse.subset
est en effet très pratique, mais n'oubliez pas d'éviter de l'utiliser à moins que vous n'utilisiez R de manière interactive. Voir l'avertissement dans la documentation de la fonction et cette question SO pour en savoir plus.Ne pas utiliser
-which()
pour cela, c'est extrêmement dangereux. Considérer:Utilisez plutôt un sous-ensemble ou la
!
fonction:J'ai appris cela d'une expérience douloureuse. Ne pas abuser
which()
!la source
setdiff
est également utile:setdiff(names(dat), c("foo", "bar"))
setdiff
proposition de @hadley est très bonne pour les longues listes de noms.Tout d'abord , vous pouvez utiliser l'indexation directe (avec des vecteurs booléens) au lieu de ré-accéder aux noms de colonne si vous travaillez avec le même bloc de données; il sera plus sûr comme l'a souligné Ista, et plus rapide à écrire et à exécuter. Donc, vous n'aurez besoin que de:
puis, réaffectez simplement les données:
Deuxièmement , plus rapide à écrire, vous pouvez directement affecter NULL aux colonnes que vous souhaitez supprimer:
Enfin , vous pouvez utiliser subset (), mais il ne peut pas vraiment être utilisé dans le code (même le fichier d'aide vous en avertit). Plus précisément, un problème pour moi est que si vous souhaitez utiliser directement la fonction drop de susbset (), vous devez écrire sans guillemets l'expression correspondant aux noms de colonne:
En bonus , voici un petit benchmark des différentes options, qui montre clairement que le sous-ensemble est le plus lent, et que la première méthode de réaffectation est la plus rapide:
Le code est ci-dessous:
la source
NULL
, mais pourquoi quand vous mettez plus de deux noms est-il nécessaire de l'attribuerlist(NULL)
? Je suis seulement curieux de savoir comment cela fonctionne, car j'ai essayé avec un seul nom et je n'ai pas besoinlist()
$
ou[[
), l'utilisation<- list(NULL)
entraînera en fait des résultats erronés. Si vous accédez à un sous-ensemble de la trame de données avec une ou plusieurs colonnes,<- list(NULL)
c'est la voie à suivre, même si elle n'est pas nécessaire pour une trame de données à une colonne (car elledf['myColumns']
sera convertie en vecteur si nécessaire).Vous pouvez également essayer le
dplyr
package:la source
dplyr::select(df2, -one_of(c('x','y')))
fonctionnera toujours (avec un avertissement) même si certaines des colonnes nommées n'existent pasVoici une solution rapide pour cela. Disons que vous avez une trame de données X avec trois colonnes A, B et C:
Si je veux supprimer une colonne, dites B, utilisez simplement grep sur les noms de colonnes pour obtenir l'index de la colonne, que vous pouvez ensuite utiliser pour omettre la colonne.
Votre nouveau bloc de données X ressemblerait à ceci (cette fois sans la colonne B):
La beauté de grep est que vous pouvez spécifier plusieurs colonnes qui correspondent à l'expression régulière. Si j'avais X avec cinq colonnes (A, B, C, D, E):
Supprimer les colonnes B et D:
EDIT: Considérant la suggestion grepl de Matthew Lundberg dans les commentaires ci-dessous:
Si j'essaie de supprimer une colonne qui n'existe pas, rien ne devrait se produire:
la source
X[,-grep("B",colnames(X))]
ne renverra aucune colonne dans le cas où aucun nom de colonne ne contientB
, plutôt que de renvoyer toutes les colonnes comme souhaité. Considérez avecX <- iris
pour un exemple. C'est le problème de l'utilisation d'indices négatifs avec des valeurs calculées. Considérezgrepl
plutôt.J'ai essayé de supprimer une colonne lors de l'utilisation du package
data.table
et j'ai obtenu un résultat inattendu. Je pense en quelque sorte que ce qui suit mérite d'être publié. Juste une petite mise en garde.[Édité par Matthew ...]
Fondamentalement, la syntaxe de
data.table
n'est PAS exactement la même quedata.frame
. Il y a en fait beaucoup de différences, voir FAQ 1.1 et FAQ 2.17. Tu étais prévenu!la source
DT[,var.out := NULL]
pour supprimer les colonnes que vous souhaitez faire.data.frame
et lesdata.table
classesJ'ai changé le code en:
Quoi qu'il en soit, la réponse de juba est la meilleure solution à mon problème!
la source
select
argument de lasubset
fonction dans mon code. je voulais juste voir comment je pouvais accéder à des colonnes arbitraires dans une boucle au cas où je voudrais faire autre chose que de simplement supprimer la colonne. l'ensemble de données d'origine a environ 1200 vars et je ne souhaite en utiliser que 4 sans savoir exactement où ils se trouvent.Voici une autre solution qui peut être utile aux autres. Le code ci-dessous sélectionne un petit nombre de lignes et de colonnes dans un grand ensemble de données. Les colonnes sont sélectionnées comme dans l'une des réponses de Juba, sauf que j'utilise une fonction de collage pour sélectionner un ensemble de colonnes avec des noms numérotés séquentiellement:
la source
la source
Je ne peux pas répondre à votre question dans les commentaires en raison du faible score de réputation.
Le code suivant vous donnera une erreur car la fonction coller retourne une chaîne de caractères
Voici une solution possible:
ou faites simplement:
la source
dfnum = df[,-c(8,9)]
la source