Объединение (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
Как я могу это сделать?
Ответы
Ответ 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