web-dev-qa-db-fra.com

Combinaison de vecteurs (cbind) de différentes longueurs

J'ai plusieurs vecteurs de longueur inégale et j'aimerais les cbind. J'ai mis les vecteurs dans une liste et j'ai essayé de combiner l'utilisation de do.call(cbind, ...):

nm <- list(1:8, 3:8, 1:5)
do.call(cbind, nm)

#      [,1] [,2] [,3]
# [1,]    1    3    1
# [2,]    2    4    2
# [3,]    3    5    3
# [4,]    4    6    4
# [5,]    5    7    5
# [6,]    6    8    1
# [7,]    7    3    2
# [8,]    8    4    3
# Warning message:
#   In (function (..., deparse.level = 1)  :
#         number of rows of result is not a multiple of vector length (arg 2)

Comme prévu, le nombre de lignes dans la matrice résultante est la longueur du vecteur le plus long et les valeurs des vecteurs les plus courts sont recyclées pour compenser la longueur.

Au lieu de cela, j'aimerais compléter les vecteurs les plus courts avec les valeurs NA pour obtenir la même longueur que le vecteur le plus long. Je voudrais que la matrice ressemble à ceci:

#      [,1] [,2] [,3]
# [1,]    1    3    1
# [2,]    2    4    2
# [3,]    3    5    3
# [4,]    4    6    4
# [5,]    5    7    5
# [6,]    6    8    NA
# [7,]    7    NA   NA
# [8,]    8    NA   NA

Comment puis-je m'y prendre?

26
Nick

Vous pouvez utiliser l'indexation. Si vous indexez un nombre supérieur à la taille de l'objet, il renvoie NA. Cela fonctionne pour tout nombre arbitraire de lignes définies avec foo:

nm <- list(1:8,3:8,1:5)

foo <- 8

sapply(nm, '[', 1:foo)

MODIFIER:

Ou sur une ligne en utilisant le plus grand vecteur en nombre de lignes:

sapply(nm, '[', seq(max(sapply(nm,length))))

Depuis R 3.2.0, vous pouvez utiliser lengths ("obtenir la longueur de chaque élément d'une liste") au lieu de sapply(nm, length):

sapply(nm, '[', seq(max(lengths(nm))))
27
Sacha Epskamp

Vous devez remplir les vecteurs avec NA avant d'appeler do.call.

nm <- list(1:8,3:8,1:5)

max_length <- max(unlist(lapply(nm,length)))
nm_filled <- lapply(nm,function(x) {ans <- rep(NA,length=max_length);
                                    ans[1:length(x)]<- x;
                                    return(ans)})
do.call(cbind,nm_filled)
5
Wojciech Sobala

Ceci est une version plus courte de la solution de Wojciech.

nm <- list(1:8,3:8,1:5)
max_length <- max(sapply(nm,length))
sapply(nm, function(x){
    c(x, rep(NA, max_length - length(x)))
})
3
Thierry

Voici une option utilisant stri_list2matrix de stringi

library(stringi)
out <- stri_list2matrix(nm)
class(out) <- 'numeric'
out
#      [,1] [,2] [,3]
#[1,]    1    3    1
#[2,]    2    4    2
#[3,]    3    5    3
#[4,]    4    6    4
#[5,]    5    7    5
#[6,]    6    8   NA
#[7,]    7   NA   NA
#[8,]    8   NA   NA
1
akrun

En retard pour la fête, mais vous pouvez utiliser le paquet cbind.fill de rowr avec fill = NA

library(rowr)
do.call(cbind.fill, c(nm, fill = NA))

#  object object object
#1      1      3      1
#2      2      4      2
#3      3      5      3
#4      4      6      4
#5      5      7      5
#6      6      8     NA
#7      7     NA     NA
#8      8     NA     NA
0
Ronak Shah