J'ai une trame de données. Appelons-le bob
:
> head(bob)
phenotype exclusion
GSM399350 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399351 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399352 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399353 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399354 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399355 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
Je voudrais concaténer les lignes de ce bloc de données (ce sera une autre question). Mais regarde:
> class(bob$phenotype)
[1] "factor"
Bob
Les colonnes de sont des facteurs. Ainsi, par exemple:
> as.character(head(bob))
[1] "c(3, 3, 3, 6, 6, 6)" "c(3, 3, 3, 3, 3, 3)"
[3] "c(29, 29, 29, 30, 30, 30)"
Je ne commence pas à comprendre cela, mais je suppose que ce sont des indices dans les niveaux des facteurs des colonnes (de la cour du roi caractacus) de bob
? Pas ce dont j'ai besoin.
Étrangement, je peux parcourir les colonnes de la bob
main et faire
bob$phenotype <- as.character(bob$phenotype)
qui fonctionne bien. Et, après quelques saisies, je peux obtenir un data.frame dont les colonnes sont des caractères plutôt que des facteurs. Ma question est donc: comment puis-je le faire automatiquement? Comment convertir un data.frame avec des colonnes factorielles en un data.frame avec des colonnes de caractères sans avoir à parcourir manuellement chaque colonne?
Question bonus: pourquoi l'approche manuelle fonctionne-t-elle?
bob
.Réponses:
Juste après Matt et Dirk. Si vous souhaitez recréer votre bloc de données existant sans modifier l'option globale, vous pouvez le recréer avec une instruction apply:
Cela convertira toutes les variables en classe "caractère", si vous souhaitez uniquement convertir les facteurs, voir la solution de Marek ci-dessous .
Comme le souligne @hadley, ce qui suit est plus concis.
Dans les deux cas,
lapply
génère une liste; cependant, en raison des propriétés magiques de R, l'utilisation de[]
dans le deuxième cas conserve la classe data.frame de l'bob
objet, éliminant ainsi la nécessité de reconvertir en data.frame en utilisantas.data.frame
avec l'argumentstringsAsFactors = FALSE
.la source
type.convert
après avoir tout castécharacter
, puis à refairefactors
unecharacter
nouvelle fois.bob[] <-
dans l'exemple oubob <-
?; le premier conserve le data.frame; le second modifie le data.frame en une liste, supprimant les noms de domaine. Jeiris[] <- lapply(iris, function(x) if (is.factor(x)) as.character(x) else {x})
Pour remplacer uniquement les facteurs:
Dans le package dplyr de la version 0.5.0, une nouvelle fonction a
mutate_if
été introduite :Le paquet purrr de RStudio donne une autre alternative:
la source
purrr
ligne renvoie une liste, pas undata.frame
!i
qui est un vecteur decolnames()
.L'option globale
peut être quelque chose que vous souhaitez définir
FALSE
dans vos fichiers de démarrage (par exemple ~ / .Rprofile). Veuillez voirhelp(options)
.la source
Si vous comprenez comment les facteurs sont stockés, vous pouvez éviter d'utiliser des fonctions basées sur les applications pour y parvenir. Ce qui ne signifie nullement que les solutions appliquées ne fonctionnent pas bien.
Les facteurs sont structurés comme des indices numériques liés à une liste de «niveaux». Cela peut être vu si vous convertissez un facteur en numérique. Donc:
Les nombres renvoyés dans la dernière ligne correspondent aux niveaux du facteur.
Notez que
levels()
renvoie un tableau de caractères. Vous pouvez utiliser ce fait pour convertir facilement et de manière compacte des facteurs en chaînes ou en chiffres comme celui-ci:Cela fonctionne également pour les valeurs numériques, à condition d'envelopper votre expression
as.numeric()
.la source
as.character(f)
, est meilleure à la fois en termes de lisibilité et d'efficacitélevels(f)[as.numeric(f)]
. Si vous vouliez être intelligent, vous pouvez utiliser à lalevels(f)[f]
place. Notez que lors de la conversion d'un facteur avec des valeurs numériques, vous obtenez un avantageas.numeric(levels(f))[f]
, par exempleas.numeric(as.character(f))
, mais c'est parce que vous n'avez qu'à convertir les niveaux en numérique, puis en sous-ensemble.as.character(f)
est très bien comme ça.Si vous voulez un nouveau bloc de données
bobc
où chaque vecteur de facteurbobf
est converti en vecteur de caractères, essayez ceci:Si vous souhaitez ensuite le reconvertir, vous pouvez créer un vecteur logique dont les colonnes sont des facteurs, et l'utiliser pour appliquer sélectivement le facteur
la source
Je fais généralement cette fonction en dehors de tous mes projets. Rapide et facile.
la source
Une autre façon est de le convertir en utilisant apply
Et une meilleure (la précédente est de classe 'matrice')
la source
as.data.frame(lapply(...
Mise à jour: voici un exemple de quelque chose qui ne fonctionne pas. Je pensais que ce serait le cas, mais je pense que l'option stringsAsFactors ne fonctionne que sur les chaînes de caractères - elle laisse les facteurs seuls.
Essaye ça:
De manière générale, chaque fois que vous rencontrez des problèmes avec des facteurs qui devraient être des caractères, il existe un
stringsAsFactors
paramètre quelque part pour vous aider (y compris un paramètre global).la source
bob
pour commencer (mais pas après coup).Ou vous pouvez essayer
transform
:Assurez-vous simplement de mettre tous les facteurs que vous souhaitez convertir en personnage.
Ou vous pouvez faire quelque chose comme ça et tuer tous les ravageurs d'un seul coup:
Ce n'est pas une bonne idée de pousser les données dans un code comme celui-ci, je pourrais faire le
sapply
partie séparément (en fait, c'est beaucoup plus facile de le faire comme ça), mais vous obtenez le point ... Je n'ai pas vérifié le code, parce que Je ne suis pas chez moi, donc j'espère que ça marche! =)Cette approche, cependant, a un inconvénient ... vous devez réorganiser les colonnes par la suite, tandis qu'avec
transform
vous, vous pouvez faire ce que vous voulez, mais au prix de "l'écriture de code de style piéton" ...Alors là ... =)
la source
Au début de votre bloc de données, vous devez
stringsAsFactors = FALSE
ignorer tous les malentendus.la source
Si vous souhaitez utiliser le
data.table
package pour les opérations sur data.frame, le problème n'est pas présent.Si vous avez déjà une colonne de facteurs dans votre jeu de données et que vous souhaitez les convertir en caractères, vous pouvez procéder comme suit.
la source
In [<-.data.table(*tmp*, sapply(bob, is.factor), : Coerced 'character' RHS to 'double' to match the column's type. Either change the target column to 'character' first (by creating a new 'character' vector length 1234 (nrows of entire table) and assign that; i.e. 'replace' column), or coerce RHS to 'double' (e.g. 1L, NA_[real|integer]_, as.*, etc) to make your intent clear and for speed. Or, set the column type correctly up front when you create the table and stick to it, please.
il est plus facile de réparer le DF et de recréer le DT.Cela fonctionne pour moi - j'ai finalement pensé à un doublure
la source
Cette fonction fait l'affaire
la source
Peut-être une option plus récente?
la source
Vous devez utiliser
convert
danshablar
lequel donne une syntaxe lisible compatible avec lestidyverse
canaux:ce qui vous donne:
la source
Avec l'
dplyr
utilisation du paquet chargési vous souhaitez uniquement modifier la
phenotype
colonne-spécifiquement.la source
Cela fonctionne en transformant tout en caractère, puis le numérique en numérique:
Adapté de: Obtenez automatiquement les types de colonne de feuille Excel
la source