Pas tellement 'Comment tu ...?' mais plus 'Comment VOUS ...?'
Si vous avez un fichier que quelqu'un vous donne avec 200 colonnes, et que vous souhaitez le réduire à quelques-unes dont vous avez besoin pour l'analyse, comment procédez-vous? Une solution offre-t-elle des avantages par rapport à une autre?
En supposant que nous ayons un bloc de données avec les colonnes col1, col2 à col200. Si vous vouliez seulement 1-100 puis 125-135 et 150-200, vous pourriez:
dat$col101 <- NULL
dat$col102 <- NULL # etc
ou
dat <- dat[,c("col1","col2",...)]
ou
dat <- dat[,c(1:100,125:135,...)] # shortest probably but I don't like this
ou
dat <- dat[,!names(dat) %in% c("dat101","dat102",...)]
Autre chose qui me manque? Je sais que c'est visuellement subjectif, mais c'est l'une de ces choses sérieuses où vous pourriez plonger et commencer à le faire dans un sens et prendre l'habitude quand il existe des moyens beaucoup plus efficaces. Tout comme cette question sur qui .
MODIFIER:
Ou, existe-t-il un moyen simple de créer un vecteur de noms de colonnes exploitable? name (dat) ne les imprime pas avec des virgules entre les deux, ce dont vous avez besoin dans les exemples de code ci-dessus, donc si vous imprimez les noms de cette façon, vous avez des espaces partout et vous devez mettre manuellement des virgules ... commande qui vous donnera "col1", "col2", "col3", ... comme sortie afin que vous puissiez facilement saisir ce que vous voulez?
J'utilise l'opérateur data.table:=
Pour supprimer des colonnes instantanément quelle que soit la taille de la table.
DT[, coltodelete := NULL]
ou
DT[, c("col1","col20") := NULL]
ou
DT[, (125:135) := NULL]
ou
DT[, (variableHoldingNamesOrNumbers) := NULL]
Toute solution utilisant <-
Ou subset
copiera la table entière . data.table L'opérateur :=
modifie simplement le vecteur interne de pointeurs vers les colonnes, en place. Cette opération est donc (presque) instantanée.
Pour supprimer des colonnes uniques, je vais simplement utiliser dat$x <- NULL
.
Pour supprimer plusieurs colonnes, mais moins de 3 à 4 environ, j'utiliserai dat$x <- dat$y <- dat$z <- NULL
.
Pour plus que cela, je vais utiliser subset
, avec des noms négatifs (!):
subset(mtcars, , -c(mpg, cyl, disp, hp))
Pour des raisons de clarté, j'utilise souvent l'argument select dans subset
. Avec des gens plus récents, j'ai appris que garder le nombre de commandes dont ils ont besoin pour ramasser au minimum aide à l'adoption. À mesure que leurs compétences augmentent, leur capacité de codage augmente également. Et le sous-ensemble est l'une des premières commandes que je montre aux gens lorsqu'ils ont besoin de sélectionner des données selon un critère donné.
Quelque chose comme:
> subset(mtcars, select = c("mpg", "cyl", "vs", "am"))
mpg cyl vs am
Mazda RX4 21.0 6 0 1
Mazda RX4 Wag 21.0 6 0 1
Datsun 710 22.8 4 1 1
....
Je suis sûr que cela testera plus lentement que la plupart des autres solutions, mais je suis rarement au point où les microsecondes font une différence.
Utilisez read.table avec les instances colClasses de "NULL" pour éviter de les créer en premier lieu:
## example data and temp file
x <- data.frame(x = 1:10, y = rnorm(10), z = runif(10), a = letters[1:10], stringsAsFactors = FALSE)
tmp <- tempfile()
write.table(x, tmp, row.names = FALSE)
(y <- read.table(tmp, colClasses = c("numeric", rep("NULL", 2), "character"), header = TRUE))
x a
1 1 a
2 2 b
3 3 c
4 4 d
5 5 e
6 6 f
7 7 g
8 8 h
9 9 i
10 10 j
unlink(tmp)
Pour les types de fichiers volumineux que j'ai tendance à obtenir, je ne ferais généralement pas cela dans R. J'utiliserais la commande cut
sous Linux pour traiter les données avant qu'elles n'atteignent R. Ce n'est pas une critique de R, juste une préférence pour l'utilisation d'outils Linux très basiques comme grep, tr, cut, sort, uniq, et parfois sed & awk (ou Perl) quand il y a quelque chose à faire sur les expressions régulières.
Une autre raison d'utiliser les commandes standard GNU est que je peux les renvoyer à la source des données et leur demander de préfiltrer les données afin de ne pas obtenir de données superflues. La plupart de mes collègues sont compétents avec Linux, moins connaissent R.
(Mise à jour) Une méthode que j'aimerais utiliser avant longtemps consiste à associer mmap
à un fichier texte et à examiner les données in sit, plutôt que de les lire du tout dans la RAM. Je l'ai fait avec C, et cela peut être extrêmement rapide.
Parfois, j'aime faire cela en utilisant des identifiants de colonne à la place.
df <- data.frame(a=rnorm(100),
b=rnorm(100),
c=rnorm(100),
d=rnorm(100),
e=rnorm(100),
f=rnorm(100),
g=rnorm(100))
as.data.frame (noms (df))
names(df)
1 a
2 b
3 c
4 d
5 e
6 f
7 g
Suppression des colonnes "c" et "g"
df[,-c(3,7)]
Cela est particulièrement utile si vous avez des cadres de données volumineux ou des noms de colonne longs que vous ne voulez pas taper. Ou les noms de colonnes qui suivent un modèle, car vous pouvez alors utiliser seq () pour supprimer.
RE: Votre modification
Vous n'avez pas nécessairement à mettre "" autour d'une chaîne, ni "," pour créer un vecteur de caractères. Je trouve cette petite astuce pratique:
x <- unlist(strsplit(
'A
B
C
D
E',"\n"))
De http://www.statmethods.net/management/subset.html
# exclude variables v1, v2, v3
myvars <- names(mydata) %in% c("v1", "v2", "v3")
newdata <- mydata[!myvars]
# exclude 3rd and 5th variable
newdata <- mydata[c(-3,-5)]
# delete variables v3 and v5
mydata$v3 <- mydata$v5 <- NULL
Je pensais que c'était vraiment intelligent de faire une liste de "ne pas inclure"
Peut utiliser la fonction setdiff
:
S'il y a plus de colonnes à conserver qu'à supprimer: Supposons que vous vouliez supprimer 2 colonnes disent col1, col2 d'un DT data.frame; vous pouvez effectuer les opérations suivantes:
DT<-DT[,setdiff(names(DT),c("col1","col2"))]
S'il y a plus de colonnes à supprimer qu'à conserver: Supposons que vous souhaitiez garder uniquement col1 et col2:
DT<-DT[,c("col1","col2")]
Je ne fais qu'adresser le montage.
@nzcoops, vous n'avez pas besoin les noms de colonnes dans un vecteur de caractères délimité par des virgules. Vous pensez à cela dans le mauvais sens. Quand tu fais
vec <- c("col1", "col2", "col3")
vous êtes créant un vecteur de caractères. Le ,
Sépare juste les arguments pris par la fonction c()
lorsque vous définissez ce vecteur. names()
et fonctions similaires retour un vecteur de caractères de noms.
> dat <- data.frame(col1 = 1:3, col2 = 1:3, col3 = 1:3)
> dat
col1 col2 col3
1 1 1 1
2 2 2 2
3 3 3 3
> names(dat)
[1] "col1" "col2" "col3"
Il est beaucoup plus facile et moins sujet aux erreurs de sélectionner parmi les éléments de names(dat)
que de traiter sa sortie dans une chaîne séparée par des virgules à partir de laquelle vous pouvez couper et coller.
Disons que nous voulons les colonnes col1
Et col2
, Sous-ensemble names(dat)
, en ne conservant que celles que nous voulons:
> names(dat)[c(1,3)]
[1] "col1" "col3"
> dat[, names(dat)[c(1,3)]]
col1 col3
1 1 1
2 2 2
3 3 3
Vous pouvez faire ce que vous voulez, mais R imprimera toujours le vecteur à l'écran entre guillemets "
:
> paste('"', names(dat), '"', sep = "", collapse = ", ")
[1] "\"col1\", \"col2\", \"col3\""
> paste("'", names(dat), "'", sep = "", collapse = ", ")
[1] "'col1', 'col2', 'col3'"
ce dernier peut donc être plus utile. Cependant, vous devez maintenant couper et coller de cette chaîne. Il vaut bien mieux travailler avec des objets qui renvoient ce que vous voulez et utiliser des routines de sous-ensemble standard pour conserver ce dont vous avez besoin.
La fonction select()
de dplyr est puissante pour le sous-ensemble de colonnes. Voir ?select_helpers
Pour une liste d'approches.
Dans ce cas, lorsque vous avez un préfixe commun et des numéros séquentiels pour les noms de colonne, vous pouvez utiliser num_range
:
library(dplyr)
df1 <- data.frame(first = 0, col1 = 1, col2 = 2, col3 = 3, col4 = 4)
df1 %>%
select(num_range("col", c(1, 4)))
#> col1 col4
#> 1 1 4
Plus généralement, vous pouvez utiliser le signe moins dans select()
pour supprimer des colonnes, comme:
mtcars %>%
select(-mpg, -wt)
Enfin, à votre question "existe-t-il un moyen facile de créer un vecteur pratique de noms de colonnes?" - oui, si vous devez modifier une liste de noms manuellement, utilisez dput
pour obtenir une liste entre guillemets séparée par des virgules que vous pouvez facilement manipuler:
dput(names(mtcars))
#> c("mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am",
#> "gear", "carb")
Si vous disposez déjà d'un vecteur de noms, qu'il existe plusieurs façons de créer, vous pouvez facilement utiliser la fonction de sous-ensemble pour conserver ou supprimer un objet.
dat2 <- subset(dat, select = names(dat) %in% c(KEEP))
Dans ce cas, KEEP est un vecteur de noms de colonnes qui est pré-créé. Par exemple:
#sample data via Brandon Bertelsen
df <- data.frame(a=rnorm(100),
b=rnorm(100),
c=rnorm(100),
d=rnorm(100),
e=rnorm(100),
f=rnorm(100),
g=rnorm(100))
#creating the initial vector of names
df1 <- as.matrix(as.character(names(df)))
#retaining only the name values you want to keep
KEEP <- as.vector(df1[c(1:3,5,6),])
#subsetting the intial dataset with the object KEEP
df3 <- subset(df, select = names(df) %in% c(KEEP))
Ce qui se traduit par:
> head(df)
a b c d
1 1.05526388 0.6316023 -0.04230455 -0.1486299
2 -0.52584236 0.5596705 2.26831758 0.3871873
3 1.88565261 0.9727644 0.99708383 1.8495017
4 -0.58942525 -0.3874654 0.48173439 1.4137227
5 -0.03898588 -1.5297600 0.85594964 0.7353428
6 1.58860643 -1.6878690 0.79997390 1.1935813
e f g
1 -1.42751190 0.09842343 -0.01543444
2 -0.62431091 -0.33265572 -0.15539472
3 1.15130591 0.37556903 -1.46640276
4 -1.28886526 -0.50547059 -2.20156926
5 -0.03915009 -1.38281923 0.60811360
6 -1.68024349 -1.18317733 0.42014397
> head(df3)
a b c e
1 1.05526388 0.6316023 -0.04230455 -1.42751190
2 -0.52584236 0.5596705 2.26831758 -0.62431091
3 1.88565261 0.9727644 0.99708383 1.15130591
4 -0.58942525 -0.3874654 0.48173439 -1.28886526
5 -0.03898588 -1.5297600 0.85594964 -0.03915009
6 1.58860643 -1.6878690 0.79997390 -1.68024349
f
1 0.09842343
2 -0.33265572
3 0.37556903
4 -0.50547059
5 -1.38281923
6 -1.18317733