Подтвердить что ты не робот

Объединение (cbind) векторов разной длины

У меня есть несколько векторов неравной длины, и я хотел бы cbind их. Я поместил векторы в список, и я попытался объединить использование 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)

Как и ожидалось, количество строк в результирующей матрице представляет собой длину самого длинного вектора, а значения более коротких векторов возвращаются, чтобы компенсировать длину.

Вместо этого я хотел бы поместить более короткие векторы с значениями NA, чтобы получить ту же длину, что и самый длинный вектор. Я бы хотел, чтобы матрица выглядела так:

#      [,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

Как я могу это сделать?

4b9b3361

Ответ 1

Вы можете использовать индексирование, если вы индексируете число за пределами размера объекта, который он возвращает NA. Это работает для любого произвольного количества строк, определенных с помощью foo:

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

foo <- 8

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

EDIT:

Или в одной строке, используя наибольший вектор как количество строк:

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

Из R 3.2.0 вы можете использовать lengths ( "получить длину каждого элемента списка" ) вместо sapply(nm, length):

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

Ответ 2

Вы должны заполнить векторы с помощью NA перед вызовом 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)

Ответ 3

Это более короткая версия решения 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)))
})

Ответ 4

Поздно, но вы можете использовать cbind.fill из пакета rowr с 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

Если у вас есть именованный list и вы хотите сохранить заголовки, вы можете использовать setNames

nm <- list(a = 1:8, b = 3:8, c = 1:5)
setNames(do.call(cbind.fill, c(nm, fill = NA)), names(nm))

#  a  b  c
#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

Ответ 5

Вот вариант использования stri_list2matrix от 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