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

Posted

技术标签:

【中文标题】组合(cbind)不同长度的向量【英文标题】:Combining (cbind) vectors of different length 【发布时间】:2011-07-28 17:41:50 【问题描述】:

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

我该怎么做?

【问题讨论】:

一闪而过:nm 【参考方案1】:

你应该在调用 do.call 之前用 NA 填充向量。

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)

【讨论】:

【参考方案2】:

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

【讨论】:

你总是最好使用vapply 而不是sapply,因为这样可以保证你得到你期望的输出类型。 @hadley 你能详细说明你的评论吗?我不明白 vapply 和 sapply 转移到这个问题的区别。 sapply 编程很危险,因为它类型不稳定 - 取决于 nm 的长度,您会得到不同的类型【参考方案3】:

您可以使用索引,如果您索引的数字超出了它返回的对象大小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))))

【讨论】:

'[' 是您在索引中使用的运算符 [ 的名称 (foo[1:10])。另见?'[' 如果第一列比其他两列短,则单行解决方案失败。 保留列名的唯一答案来自@Ronak Shah,使用rowr 包。是否有保留列名的基本 R 替代方案?【参考方案4】:

聚会迟到了,但您可以使用来自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

【讨论】:

【参考方案5】:

这是一个使用来自stringistri_list2matrix 的选项

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

【讨论】:

以上是关于组合(cbind)不同长度的向量的主要内容,如果未能解决你的问题,请参考以下文章

查找两个不同长度的向量之间的所有组合

向量与子向量长度 n 的组合

pandas 相当于 R 的 cbind(垂直连接/堆叠向量)

使用逻辑 OR 组合列表中的逻辑向量

r函数知识总结

如何到达内部向量可能具有不同长度的向量向量的第 N 个元素?