我有一个矢量:
data <- c("ta", "tb", "tc", "tk", "tf")
如何将此向量转换为一个列表,其中包含n个(其中n的范围从2到长度(数据)-1)相邻元素的每个可能组合?该列表应如下所示(每行代表一个列表元素):
"ta", "tb"
"tb", "tc"
"tc", "tk"
"tk", "tf"
"ta", "tb", "tc"
"tb", "tc", "tk"
"tc", "tk", "tf"
"ta", "tb", "tc", "tk"
"tb", "tc", "tk", "tf"
我需要多次执行此操作,因此速度很重要。谢谢!
答案 0 :(得分:2)
这是一种方式:
adj.poss <- function(x) {
n <- length(x)
stopifnot(n > 2L)
idx <- expand.grid(start = 1L:n, len = 2L:(n-1L))
idx$end <- idx$start + idx$len - 1L
idx <- idx[idx$end <= n, ]
Map(function(start, end) x[start:end], idx$start, idx$end)
}
其中adj.poss(data)
给出您的预期输出,其顺序与您指定的完全相同。
答案 1 :(得分:2)
以下是使用data.table
的{{1}}函数的方法。基本上,vecseq
取x中的每个数字,来自相应索引的y值,并构造序列x:(x + len)。也就是说,vecseq(x, y, clamp)
构造序列vecseq(c(1L, 4L), c(2L, 6L), 5L)
。 c(1L, 2L, 4L, 5L, 6L)
参数只是 应该<=> =答案长度的参数。如果你不知道,你可以给出一个相对较大的数字。
我们的想法是使用clamp
生成索引,然后拆分以相应地获取列表。我希望通过逐步运行下面的代码,事情应该是显而易见的(稍加努力:))。
vecseq
这看起来非常快,与@ flodel的(优秀)答案相同。当数据长度达到250左右时,差异大约为0.2秒(此解决方案更快)。所以,没有太大区别。
答案 2 :(得分:2)
myFun <- function(Data) {
A <- lapply(2:(length(Data)-1), sequence)
B <- lapply(rev(vapply(A, length, 1L))-1, function(x) c(0, sequence(x)))
unlist(lapply(seq_along(A), function(x) {
lapply(B[[x]], function(y) Data[A[[x]]+y])
}), recursive = FALSE, use.names = FALSE)
}
用法:
myFun(data)
以下是使用“zoo”中rollapply
的解决方案:
myFun <- function(Data, singles = FALSE) {
require(zoo)
x <- 2:(length(Data)-1)
out <- lapply(x, function(y) rollapply(Data, FUN = c, width = y))
if (isTRUE(singles)) {
out <- unlist(lapply(out, function(y) split(y, sequence(nrow(y)))),
recursive = FALSE, use.names = FALSE)
}
out
}
如果要按行分割上述输出(新列表项中的每个项目),请使用singles = TRUE
参数:
myFun(data, singles = TRUE)
# [[1]]
# [1] "ta" "tb"
#
# [[2]]
# [1] "tb" "tc"
#
#######
# SNIP
#######
#
# [[8]]
# [1] "ta" "tb" "tc" "tk"
#
# [[9]]
# [1] "tb" "tc" "tk" "tf"