web-dev-qa-db-fra.com

Créer une trame de données de longueurs inégales

Bien que les colonnes du bloc de données doivent avoir le même nombre de lignes, existe-t-il un moyen de créer un bloc de données de longueurs inégales. Je ne suis pas intéressé à les enregistrer en tant qu'éléments séparés d'une liste, car je dois souvent envoyer ces informations par e-mail aux gens sous forme de fichier csv, ce qui est plus simple en tant que bloc de données.

x = c(rep("one",2))
y = c(rep("two",10))
z = c(rep("three",5))
cbind(x,y,z)

Dans le code ci-dessus, la fonction cbind() recycle simplement les colonnes les plus courtes afin qu'elles aient toutes 10 éléments dans chaque colonne. Comment puis-je le modifier juste pour que les longueurs soient 2, 10 et 5.

J'ai fait cela dans le passé en faisant ce qui suit, mais c'est inefficace.

  df = data.frame(one=c(rep("one",2),rep("",8)), 
           two=c(rep("two",10)), three=c(rep("three",5), rep("",5))) 
22
ATMathew

Désolé, ce n'est pas exactement ce que vous avez demandé, mais je pense qu'il peut y avoir une autre façon d'obtenir ce que vous voulez.

Premièrement, si les vecteurs sont de longueurs différentes, les données ne sont pas vraiment tabulaires, n'est-ce pas? Que diriez-vous simplement de l'enregistrer dans différents fichiers CSV? Vous pouvez également essayer les formats ascii qui permettent de stocker plusieurs objets ( json , XML ).

Si vous pensez que les données sont vraiment tabulaires, vous pouvez remplir les NA:

> x = 1:5
> y = 1:12
> max.len = max(length(x), length(y))
> x = c(x, rep(NA, max.len - length(x)))
> y = c(y, rep(NA, max.len - length(y)))
> x
 [1]  1  2  3  4  5 NA NA NA NA NA NA NA
> y
 [1]  1  2  3  4  5  6  7  8  9 10 11 12

Si vous devez absolument faire un data.frame avec des colonnes inégales, vous pouvez inverser la vérification, à vos risques et périls:

> x = 1:5
> y = 1:12
> df = list(x=x, y=y)
> attributes(df) = list(names = names(df),
    row.names=1:max(length(x), length(y)), class='data.frame')
> df
      x  y
1     1  1
2     2  2
3     3  3
4     4  4
5     5  5
6  <NA>  6
7  <NA>  7
 [ reached getOption("max.print") -- omitted 5 rows ]]
Warning message:
In format.data.frame(x, digits = digits, na.encode = FALSE) :
  corrupt data frame: columns will be truncated or padded with NAs
26
Owen

Une autre approche du rembourrage:

na.pad <- function(x,len){
    x[1:len]
}

makePaddedDataFrame <- function(l,...){
    maxlen <- max(sapply(l,length))
    data.frame(lapply(l,na.pad,len=maxlen),...)
}

x = c(rep("one",2))
y = c(rep("two",10))
z = c(rep("three",5))

makePaddedDataFrame(list(x=x,y=y,z=z))

La fonction na.pad() exploite le fait que R remplira automatiquement un vecteur avec des NA si vous essayez d'indexer des éléments inexistants.

makePaddedDataFrame() trouve juste la plus longue et remplit le reste jusqu'à une longueur correspondante.

7
Peter M

Pour amplifier la réponse de @ goodside, vous pouvez faire quelque chose comme

L <- list(x,y,z)
cfun <- function(L) {
  pad.na <- function(x,len) {
   c(x,rep(NA,len-length(x)))
  }
  maxlen <- max(sapply(L,length))
  do.call(data.frame,lapply(L,pad.na,len=maxlen))
}

(non testé).

6
Ben Bolker

Ce n'est pas possible. Le plus proche possible est de remplir les espaces "vides" avec la valeur NA.

3
goodside