Je souhaite trouver un moyen de créer une donnée de données. à l'aide de cbind()
pour rejoindre de nombreux objets distincts. Par exemple, si A, B, C & D, tous les vecteurs de la même longueur, on peut créer data.frame
ABCD avec
ABCD <- cbind(A,B,C,D)
Cependant, lorsque le nombre d'objets à combiner devient grand, il devient fastidieux de taper tous leurs noms. En outre, existe-t-il un moyen d'appeler cbind()
sur un vecteur de noms d'objet, par exemple.
objs <- c("A", "B", "C", "D")
ABCD <- cbind(objs)
ou sur une liste contenant tous les objets à combiner, par exemple.
obj.list <- list(A,B,C,D)
ABCD <- cbind(obj.list)
Actuellement, la seule solution de contournement que je peux penser est d'utiliser paste()
, cat()
, write.table()
et source()
pour construire les arguments à cbind()
, écrivez-le comme un script et source. Cela ressemble à un très mauvais kludge. En outre, j'ai examiné do.call()
mais ne semble pas sembler trouver un moyen d'accomplir ce que je veux avec elle.
Les do.call
La fonction est très utile ici:
A <- 1:10
B <- 11:20
C <- 20:11
> do.call(cbind, list(A,B,C))
[,1] [,2] [,3]
[1,] 1 11 20
[2,] 2 12 19
[3,] 3 13 18
[4,] 4 14 17
[5,] 5 15 16
[6,] 6 16 15
[7,] 7 17 14
[8,] 8 18 13
[9,] 9 19 12
[10,] 10 20 11
Vous devez d'abord get
les objets que vous souhaitez et les stocker en tant que liste; Si vous pouvez construire leurs noms comme chaînes, vous utilisez la fonction get
. Ici, je crée deux variables, A
et B
:
> A <- 1:4
> B <- rep(LETTERS[1:2],2)
Je construis ensuite un vecteur de caractère contenant leurs noms (stockés comme ns
) et get
ces variables utilisant lapply
. J'ai ensuite défini les noms de la liste pour être les mêmes que leurs noms d'origine.
> (ns <- LETTERS[1:2])
[1] "A" "B"
> obj.list <- lapply(ns, get)
> names(obj.list) <- ns
> obj.list
$A
[1] 1 2 3 4
$B
[1] "A" "B" "A" "B"
Ensuite, vous pouvez utiliser do.call
; Le premier argument est la fonction que vous souhaitez et la seconde est une liste avec les arguments que vous souhaitez transmettre.
> do.call(cbind, obj.list)
A B
[1,] "1" "A"
[2,] "2" "B"
[3,] "3" "A"
[4,] "4" "B"
Cependant, comme al3xa note correctement, cela fait une matrice, pas une image de données, ce qui peut ne pas être ce que vous voulez si les variables sont différentes classes; Ici, mon A
a été contraint à un vecteur de caractère au lieu d'un vecteur numérique. Pour créer une trame de données d'une liste, vous appelez simplement data.frame
dessus; Ensuite, les classes des variables sont conservées.
> (AB <- data.frame(obj.list))
A B
1 1 A
2 2 B
3 3 A
4 4 B
> sapply(AB, class)
A B
"integer" "factor"
> str(AB)
'data.frame': 4 obs. of 2 variables:
$ A: int 1 2 3 4
$ B: Factor w/ 2 levels "A","B": 1 2 1 2
Cependant, vous devriez nuire à cet esprit que cbind
renvoie un vecteur atomique (matrice) lorsqu'il est appliqué uniquement sur des vecteurs atomiques (double
dans ce cas). Comme vous pouvez le constater dans les réponses de @ Prasad et @ Aaron, l'objet résultant est une matrice. Si vous spécifiez d'autres vecteurs atomiques (entier, double, logique, complexe) ainsi que le vecteur de caractère, ils seront forcés à caractère. Et puis vous avez un problème - vous devez les convertir aux cours souhaités. Donc,
si A, B, C & D, les vecteurs sont tous des vecteurs de la même longueur, on peut créer des données.frame ABCD avec
ABCD <- data.frame(A, B, C, D)
Peut-être devriez-vous demander "Comment puis-je collecter facilement divers vecteurs de longueur égale et les mettre dans un data.frame
"?cbind
est génial, mais parfois ce n'est pas ce que vous cherchez ...
Vous pouvez mettre tous les vecteurs dans l'environnement dans la liste en utilisant ESAPPLY.
obj.list <- eapply(.GlobalEnv,function(x) if(is.vector(x)) x)
obj.list <- obj.list[names(obj.list) %in% LETTERS]