找到多个向量的组合以在 R 中明智地填充更大的向量元素(根据它们的索引)

Find a combination of multiple vectors to fill a bigger vector element-wisely in R (according to their indexes)

非常感谢对此任务的任何提示。

我感兴趣的原始向量中有重复序列,所以我使用 rle function,加上一些额外的管理,以获得与我感兴趣的原始值对应的索引向量.

我做了一个简单的模拟来更好地解释我的目的。假设我对长度为 20 的向量中重复的 pattern/label“1”感兴趣。例如:

vec_list <- list (
vec1 = c(2,1,1,1,2,2,3,3,3,1,1,1,3,3,2,2,1,1,1,1),
vec2 = c(3,3,3,3,2,2,2,1,1,1,2,2,2,2,3,3,3,1,1,2),
vec3 = c(2,2,2,1,1,1,3,3,3,3,1,1,1,1,1,2,2,2,3,3) )

当我得到重复值的索引等于 1 时,我得到:

# for replication
indexes <- list(
vec1.a = 2:4, vec1.b = 10:12, vec1.c = 17:20,
vec2.a = 8:10, vec2.b = 18:19,
vec3.a = 4:6, vec3.b =11:15 )

结果列表:

indexes
$vec1.a
[1] 2 3 4

$vec1.b
[1] 10 11 12

$vec1.c
[1] 17 18 19 20

$vec2.a
[1]  8  9 10

$vec2.b
[1] 18 19

$vec3.a
[1] 4 5 6

$vec3.b
[1] 11 12 13 14 15


因此,对于列表中的每个向量,我得到新的向量,其值的索引对应于 1,即 "blocks" 值的顺序。我想以编程方式验证此类块的所有可能组合以填充矢量而不重叠块。允许多种组合。

为了更好地说明我的目的,我做了一些图片:


我不希望得到一个圆满的答案,但我确实希望我可以遵循任何方向来实现这个目标。例如,直到最近我才知道 rle function,它大大简化了我捕获这些重复值及其索引的任务。如果你知道这方面的任何功能,请在下面评论,我将不胜感激!

这是一道难题。让我们从以编程方式生成向量开始 indexes:

indexes <- list(
    vec1.a = 2:4, vec1.b = 10:12, vec1.c = 17:20,
    vec2.a = 8:10, vec2.b = 18:19,
    vec3.a = 4:6, vec3.b =11:15 )

通过使用 which 以及 difflapply,我们有以下内容:

myOnes <- do.call(c, lapply(vec_list, function(x) {
    temp <- which(x == 1)
    ind <- c(1, which(diff(temp) > 1) + 1, length(temp) + 1)
    lapply(1:(length(ind) - 1), function(y) {
        temp[ind[y]:(ind[y + 1] - 1)]
    })
}))

myOnes
$vec11
[1] 2 3 4

$vec12
[1] 10 11 12

$vec13
[1] 17 18 19 20

$vec21
[1]  8  9 10

$vec22
[1] 18 19

$vec31
[1] 4 5 6

$vec32
[1] 11 12 13 14 15

现在,我们需要确定哪些向量与其他向量没有重叠。由于我们按递增顺序比较这些向量,因此不需要重新检查较早的向量,因为我们已经检查过它(例如,检查 vec22 和 vec13 是多余的,因为当 vec13 是第一个被比较的向量时,我们已经检查了这个组合).同样,使用 base R 中的函数我们有:

lenOnes <- length(myOnes)

noOverLap <- lapply(1:(lenOnes - 1), function(x) {
    which(sapply((x + 1):lenOnes, function(y) {
        length(intersect(myOnes[[x]], myOnes[[y]])) == 0
    })) + x
})

noOverLap
[[1]]            ## The first vector above i.e. vec11 only
[1] 2 3 4 5 7    ## overlaps the sixth vector i.e. vec31

[[2]]
[1] 3 5 6

[[3]]
[1] 4 6 7

[[4]]            ## The fourth vector above i.e. vec21 doesn't
[1] 5 6 7        ## overlap any vector beyond the fourth one

[[5]]
[1] 6 7

[[6]]
[1] 7

这看起来很有希望,而且还不错。现在我们需要以某种方式利用这个新创建的列表来找到所有非重叠向量网络。这里面写满了递归。

myList <- vector("list")
n <- 0

## helper function for adding elements to our list
## ... this keeps our recursion function cleaner
addToList <- function(v) {
    if (n == 0) {
        myList[[n <<- n + 1]] <<- v
    } else if (!isTRUE(all.equal(v, myList[[n]]))) {
        myList[[n <<- n + 1]] <<- v
    }
}

recurse <- function(v, x, z) {
    if (x <= length(noOverLap)) {
        b <- intersect(z, noOverLap[[x]])
        if (length(b) > 0)
            for (i in b)
                recurse(c(v, i), i, b)
    } else {
        addToList(v)
    }
    addToList(v)
}

您还会注意到我们使用 <<-(即 scoping assignment)来更新我们的列表。

运行 我们对列表的每个索引 noOverLap 的递归函数,我们获得不重叠的向量的每个组合:

for (i in seq_along(noOverLap))
    recurse(i, i, noOverLap[[i]])

head(myList)
[[1]]
[1] 1 2 3

[[2]]
[1] 1 2 5

[[3]]
[1] 1 2

[[4]]
[1] 1 3 4 7

[[5]]
[1] 1 3 4

[[6]]
[1] 1 3 7

## looking at some of the middle elements
myList[21:25]    ## length(myList) is 43
[[1]]
[1] 2

[[2]]
[1] 3 4 6 7

[[3]]
[1] 3 4 6

[[4]]
[1] 3 4 7

[[5]]
[1] 3 4

上面的输出告诉我们 myOnes 中不重叠的向量的每个组合。

让我们仔细看看 myList[[4]] 以了解发生了什么:

myList[[4]]
[1] 1 3 4 7

myOnes[myList[[4]]]    ## the 1st, 3rd, 4th, and 7th vectors of myOnes
$vec11
[1] 2 3 4

$vec13
[1] 17 18 19 20

$vec21
[1]  8  9 10

$vec32
[1] 11 12 13 14 15

为了证明不存在重叠,我们可以连接这些向量,对它们进行排序,进行差异计算并确保没有零值。

unlist(myOnes[myList[[4]]])
vec111 vec112 vec113 vec131 vec132 vec133 vec134 vec211 vec212 vec213 vec321 vec322 vec323 vec324 vec325 
     2      3      4     17     18     19     20      8      9     10     11     12     13     14     15

 sort(unlist(myOnes[myList[[4]]]))
 vec111 vec112 vec113 vec211 vec212 vec213 vec321 vec322 vec323 vec324 vec325 vec131 vec132 vec133 vec134 
      2      3      4      8      9     10     11     12     13     14     15     17     18     19     20 

 diff(sort(unlist(myOnes[myList[[4]]])))
 vec112 vec113 vec211 vec212 vec213 vec321 vec322 vec323 vec324 vec325 vec131 vec132 vec133 vec134 
      1      1      4      1      1      1      1      1      1      1      2      1      1      1 

 any(diff(sort(unlist(myOnes[myList[[4]]]))) == 0)
 [1] FALSE

最后要获得我们的指数组合,我们可以执行以下操作:

indCombos <- lapply(myList, function(x) unlist(myOnes[x]))

head(indCombos)
[[1]]
vec111 vec112 vec113 vec121 vec122 vec123 vec131 vec132 vec133 vec134 
     2      3      4     10     11     12     17     18     19     20 

[[2]]
vec111 vec112 vec113 vec121 vec122 vec123 vec221 vec222 
     2      3      4     10     11     12     18     19 

[[3]]
vec111 vec112 vec113 vec121 vec122 vec123 
     2      3      4     10     11     12 

[[4]]
vec111 vec112 vec113 vec131 vec132 vec133 vec134 vec211 vec212 vec213 vec321 vec322 vec323 vec324 vec325 
     2      3      4     17     18     19     20      8      9     10     11     12     13     14     15 

[[5]]
vec111 vec112 vec113 vec131 vec132 vec133 vec134 vec211 vec212 vec213 
     2      3      4     17     18     19     20      8      9     10 

[[6]]
vec111 vec112 vec113 vec131 vec132 vec133 vec134 vec321 vec322 vec323 vec324 vec325 
     2      3      4     17     18     19     20     11     12     13     14     15