Concaténer les lignes d'une trame de données
Je voudrais prendre un bloc de données avec des caractères et des nombres, et de les enchaîner tous les éléments de chaque ligne dans une chaîne unique, qui serait stocké en un seul élément dans un vecteur. Comme un exemple, je fais un bloc de données, de chiffres et de lettres, et puis je voudrais concaténer la première ligne via la fonction "coller", et espérons-le, retourner la valeur "A1"
df <- data.frame(letters = LETTERS[1:5], numbers = 1:5)
df
## letters numbers
## 1 A 1
## 2 B 2
## 3 C 3
## 4 D 4
## 5 E 5
paste(df[1,], sep =".")
## [1] "1" "1"
Donc coller est la conversion de chaque élément de la ligne dans un entier qui correspond à l'index du niveau correspondant du " comme si il s'agissait d'un facteur, et il le maintient d'un vecteur de longueur deux. (Je sais que/croire que les facteurs qui sont contraints à être des personnages se comportent de cette façon, mais en tant que R n'est pas de stocker df[1,] comme un facteur à tout (testé par est.facteur(), je ne peux pas vérifier qu'il est en fait un index pour un niveau)
is.factor(df[1,])
## [1] FALSE
is.vector(df[1,])
## [1] FALSE
Donc, si ce n'est pas un vecteur, alors il est logique qu'elle se comporte bizarrement, mais je ne peux pas le forcer dans un vecteur
> is.vector(as.vector(df[1,]))
[1] FALSE
À l'aide de as.character
ne semble pas aider dans mes tentatives
Quelqu'un peut expliquer ce comportement?
- Avez-vous essayé d'ajouter le
stringsAsFactors=FALSE
argument à vos données.cadre de la création?
Vous devez vous connecter pour publier un commentaire.
Tandis que d'autres ont mis l'accent sur les raisons de votre code ne fonctionne pas et comment l'améliorer, je vais essayer de me concentrer plus sur d'obtenir le résultat que vous souhaitez. À partir de votre description, il semble que vous pouvez facilement obtenir ce que vous voulez en utilisant la pâte:
Vous pouvez modifier
df$letters
de caractère à l'aide dedf$letters <- as.character(df$letters)
si vous ne souhaitez pas utiliser lestringsAsFactors
argument.Mais supposons que ce n'est pas ce que vous voulez. Supposons que vous avez des centaines de colonnes et que vous souhaitez coller tous ensemble. On peut le faire avec votre exemple minimal trop:
EDIT: la méthode Alternative et de l'explication:
J'ai réalisé que le problème que vous rencontrez est une combinaison du fait que vous êtes en utilisant un facteur et que vous êtes à l'aide de la
sep
argument au lieu decollapse
(comme @adibender ramassé). La différence est quesep
donne le séparateur entre deux vecteurs distincts etcollapse
donne des séparateurs à l'intérieur d'un vecteur. Lorsque vous utilisezdf[1,]
, vous offre un unique vecteur depaste
et par conséquent, vous devez utiliser lecollapse
argument. À l'aide de votre idée de faire de chaque ligne et de la concaténation d'entre eux, la ligne de code suivante permettra de faire exactement ce que vous voulez:Ok, maintenant, pour les explications:
Pourquoi ne pas
as.list
travail?as.list
convertit un objet à une liste. Donc, il ne le travail. Il vous permet de convertir votre dataframe à une liste et ensuite ignorer lessep=""
argument.c
combine des objets ensemble. Techniquement, un dataframe est juste une liste où chaque colonne est un élément et tous les éléments ont la même longueur. Alors, quand je le combiner avecsep=""
, il devient tout simplement une liste avec les colonnes de la dataframe comme éléments.Pourquoi utiliser
do.call
?do.call
vous permet d'appeler une fonction à l'aide d'une liste nommée comme arguments. Vous ne pouvez pas simplement jeter la liste directement danspaste
, parce qu'il n'aime pas dataframes. Il est conçu pour la concaténation de vecteurs. Alors, n'oubliez pas quedfargs
est une liste contenant un vecteur de lettres, un vecteur de nombres et la sep qui est un vecteur de longueur 1 contenant seulement "". Lorsque j'utilisedo.call
, la pâte obtenue fonction est essentiellementpaste(letters, numbers, sep)
.Mais que faire si mon original dataframe avait colonnes
"letters", "numbers", "squigs", "blargs"
après que j'ai ajouté le séparateur comme je l'ai fait avant? Ensuite, la fonction coller à traversdo.call
ressemblerait à:Donc, vous voyez que cela fonctionne pour n'importe quel nombre de colonnes.
C'est en effet un peu bizarre, mais c'est aussi ce qui est censé se produire.
Lorsque vous créez le
data.frame
comme vous l'avez fait, colonneletters
est stockée en tant quefactor
. Naturellement facteurs ont aucune commande, donc quandas.numeric()
est appliqué à un facteur de il retourne la commande de ce facteur. Par exemple:A
est le premier niveau du facteurdf[, 1]
doncA
est converti à la valeur1
, quandas.numeric
est appliquée. C'est ce qui arrive lorsque vous appelezpaste(df[1, ])
. Puisque les colonnes 1 et 2 sont de classe différente, collez d'abord transforme les deux éléments de la ligne 1 du numérique puis de caractères.Quand vous voulez concaténer les deux colonnes, vous devez d'abord transformer la première ligne de caractère:
Comme @sébastien-c souligné, vous pouvez également utiliser
stringsAsFactors = FALSE
dans la création des données.une image, vous pouvez omettre leas.character()
étape.Pour ceux utilisant la bibliothèque(tidyverse), vous pouvez simplement utiliser l'unite de la fonction.
Cela vous donnera une nouvelle colonne intitulée "ensemble" avec A1, B2, etc
?tidyverse::unite
-- il n'y a rien. Pour les gens qui veulent juste utiliser attaquer le problème à la main et ne voulez pas charger l'ensemble, ça serait bien de savoir qu'ils peuvent charger des tidyr. Btw, je ne critique pas la réponse, qui je upvoted, juste ce qui suggère une amélioration.si vous souhaitez commencer avec
.. alors il n'y a pas de règle générale sur la façon
df$letters
sera interprété par une fonction donnée. C'est un facteur pour la modélisation des fonctions de caractère pour certains et entier pour d'autres. Même la même fonction, tels que la pâte peut l'interpréter différemment, en fonction de la façon dont vous l'utiliser:Logique, sauf qu'il sera probablement inutile une fois que vous connaissez le fonctionnement interne de chaque fonction.
Les facteurs semblent être convertis en nombres entiers lorsqu'un argument est converti vecteur (comme vous le savez, les trames de données sont des listes de vecteurs de longueur égale, de sorte que la première ligne d'un bloc de données est également une liste, et quand il est forcé d'être un vecteur, quelque chose comme cela arrive:)
Je ne sais pas comment
apply
réalise ce qu'il fait (c'est à dire, les facteurs sont représentés par les valeurs de caractères) -- si vous êtes intéressés, regardez le code source. Il peut être utile de savoir, cependant, que vous pouvez faire confiance (dans ce sens)apply
(à cette occasion). Plus généralement, il est utile de stocker chaque morceau de données dans un bon format, qui comprend stocker des chaînes de caractères comme des chaînes de caractères, c'est à dire, à l'aide destringsAsFactors=FALSE
.Btw, introduction R livre devrait avoir cette idée dans un sous-titre. Par exemple, mon plan pour la retraite est d'écrire "Une (pas si) introduction en douceur à la zen de données de la pêche avec R, le stringsAsFactors=FALSE façon".