web-dev-qa-db-fra.com

combinaison de deux trames de données de longueurs différentes

J'ai deux trames de données.
La première est composée d'une seule colonne et de 10 lignes.
La seconde est de 3 colonnes et 50 lignes.

Lorsque j'essaie de combiner cela en utilisant cbind, cela donne cette erreur:

Erreur dans data.frame (..., check.names = FALSE):

Quelqu'un peut-il suggérer une autre fonction pour ce faire?
P.S J'ai aussi essayé cela en utilisant des listes, mais cela donne la même erreur.

Le bloc de données composé de 3 colonnes doit être les 3 premières colonnes d'un fichier CSV, tandis que le bloc de données avec une colonne doit être la quatrième colonne de ce fichier, lorsque j'écris avec le write.table une fonction. Les 3 premières colonnes ont 50 lignes et la quatrième colonne devrait occuper les 10 premières lignes.

31
Matt

Dans le package plyr, il y a une fonction rbind.fill qui fusionnera data.frames et introduira NA pour les cellules vides:

library(plyr)
combined <- rbind.fill(mtcars[c("mpg", "wt")], mtcars[c("wt", "cyl")])
combined[25:40, ]

    mpg    wt cyl
25 19.2 3.845  NA
26 27.3 1.935  NA
27 26.0 2.140  NA
28 30.4 1.513  NA
29 15.8 3.170  NA
30 19.7 2.770  NA
31 15.0 3.570  NA
32 21.4 2.780  NA
33   NA 2.620   6
34   NA 2.875   6
35   NA 2.320   4
34
Andrie

Je ne sais pas du tout ce que le PO est réellement après, compte tenu des commentaires de suivi. Il est possible qu'ils recherchent réellement un moyen d'écrire les données dans un fichier.

Mais supposons que nous recherchions vraiment cbind plusieurs blocs de données de longueurs différentes.

cbind finira par appeler data.frame, dont les fichiers d'aide indiquent:

Les objets passés à data.frame devraient avoir le même nombre de lignes, mais les vecteurs atomiques, les facteurs et les vecteurs de caractères protégés par I seront recyclés un certain nombre de fois si nécessaire (y compris à partir de R 2.9.0, éléments d'arguments de liste).

donc dans l'exemple réel de l'OP, il ne devrait pas être une erreur, car R devrait recycler les vecteurs les plus courts pour être de longueur 50. En effet, lorsque Je lance ce qui suit:

set.seed(1)
a <- runif(50)
b <- 1:50
c <- rep(LETTERS[1:5],length.out = 50)
dat1 <- data.frame(a,b,c)
dat2 <- data.frame(d = runif(10),e = runif(10))
cbind(dat1,dat2)

Je ne reçois aucune erreur et la trame de données plus courte est recyclée comme prévu. Cependant, lorsque je lance ceci:

set.seed(1)
a <- runif(50)
b <- 1:50
c <- rep(LETTERS[1:5],length.out = 50)
dat1 <- data.frame(a,b,c)
dat2 <- data.frame(d = runif(9), e = runif(9))
cbind(dat1,dat2)

J'obtiens l'erreur suivante:

Error in data.frame(..., check.names = FALSE) : 
  arguments imply differing number of rows: 50, 9

Mais la chose merveilleuse à propos de R est que vous pouvez lui faire faire presque tout ce que vous voulez, même si vous ne devriez pas. Par exemple, voici une fonction simple qui cbind trames de données de longueur inégale et remplira automatiquement les plus courtes avec NAs:

cbindPad <- function(...){
args <- list(...)
n <- sapply(args,nrow)
mx <- max(n)
pad <- function(x, mx){
    if (nrow(x) < mx){
        nms <- colnames(x)
        padTemp <- matrix(NA, mx - nrow(x), ncol(x))
        colnames(padTemp) <- nms
        if (ncol(x)==0) {
          return(padTemp)
        } else {
        return(rbind(x,padTemp))
          }
    }
    else{
        return(x)
    }
}
rs <- lapply(args,pad,mx)
return(do.call(cbind,rs))
}

qui peut être utilisé comme ceci:

set.seed(1)
a <- runif(50)
b <- 1:50
c <- rep(LETTERS[1:5],length.out = 50)
dat1 <- data.frame(a,b,c)
dat2 <- data.frame(d = runif(10),e = runif(10))
dat3 <- data.frame(d = runif(9), e = runif(9))
cbindPad(dat1,dat2,dat3)

Je ne garantis pas que cette fonction fonctionne dans tous les cas; il s'agit uniquement d'un exemple.

MODIFIER

Si l'objectif principal est de créer un fichier csv ou texte, tout ce dont vous avez besoin pour le faire est de modifier la fonction à remplir en utilisant "" plutôt que NA puis faites quelque chose comme ceci:

dat <- cbindPad(dat1,dat2,dat3)
rs <- as.data.frame(apply(dat,1,function(x){paste(as.character(x),collapse=",")}))

puis utilisez write.table sur rs.

20
joran

En se référant à la réponse d'Andrie, suggérant d'utiliser plyr::rbind.fill(): combiné avec t() vous avez quelque chose comme cbind.fill() (qui ne fait pas partie de plyr) qui construira votre bloc de données en tenant compte des numéros de cas identiques.

1
søren