R语言 组合(cbind)不同长度的向量

azpvetkf  于 2023-04-27  发布在  其他
关注(0)|答案(6)|浏览(281)

我有几个不等长的向量,我想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

我该怎么做呢?

v7pvogib

v7pvogib1#

你可以使用索引,如果你索引一个超过对象大小的数字,它会返回NA。这适用于任何用foo定义的任意数量的行:

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

foo <- 8

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

编辑:
或者在一行中使用最大向量作为行数:

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

R 3.2.0中,你可以使用lengths(“获取列表中每个元素的长度”)来代替sapply(nm, length)

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

cbeh67ev2#

在调用do.call之前,应该用NA填充vectors。

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)
n1bvdmb6

n1bvdmb63#

这是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)))
})
nbnkbykc

nbnkbykc4#

下面是使用stri_list2matrix from 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
ocebsuys

ocebsuys5#

迟到了,但您可以将rowr包中的cbind.fillfill = 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
cbeh67ev

cbeh67ev6#

你必须使用length<-使所有列表元素具有相同的长度,然后你可以使用cbind得到一个矩阵。

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

do.call(cbind, lapply(nm, `length<-`, max(lengths(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   NA
#[7,]    7   NA   NA
#[8,]    8   NA   NA

基准

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

bench::mark(
"[" = sapply(nm, '[', seq(max(lengths(nm)))),
"length<-" = do.call(cbind, lapply(nm, `length<-`, max(lengths(nm)))) )
#  express…¹     min  median itr/s…² mem_a…³ gc/se…⁴ n_itr  n_gc total…⁵ result  
#  <bch:exp> <bch:t> <bch:t>   <dbl> <bch:b>   <dbl> <int> <dbl> <bch:t> <list>  
#1 [         36.19µs 40.56µs  24412.      0B    12.2  9995     5 409.4ms <int[…]>
#2 length<-   8.63µs  9.88µs 100367.      0B    20.1  9998     2  99.6ms <int[…]>

在这种情况下,使用length<-[快4倍。

相关问题