【问题标题】:From a list of numeric values, create a list of indices从数值列表中,创建索引列表
【发布时间】:2021-12-29 11:34:21
【问题描述】:

我有一个数字向量列表:

a <- list(c(2, 3, 4, 5, 6, 7), c(4, 5, 6, 7, 8), c(6, 7, 8, 9, 10))

> a
[[1]]
[1] 2 3 4 5 6 7

[[2]]
[1] 4 5 6 7 8

[[3]]
[1]  6  7  8  9 10

我想创建一个列表,其中每个元素对应于原始列表“a”中从 1 到最大值的值。新列表的每个元素中的值是包含焦点值的原始列表中的索引

例如,结果中的第一个元素包含“a”中值为 1 的索引。由于没有元素包含 1,因此结果为 NULL。第二个元素包含“a”中值为 2 的索引,即第一个元素 1。值 4 在元素 1 和 2 中找到。

> res
[[1]]
NULL

[[2]]
[1] 1

[[3]]
[1] 1

[[4]]
[2] 1 2

[[5]]
[2] 1 2

[[6]]
[3] 1 2 3

[[7]]
[3] 1 2 3

[[8]]
[2] 2 3

[[9]]
[1] 3

[[10]]
[1] 3 

我用嵌套循环尝试过这个,但是它花费了太多时间并且在循环中增长列表非常慢。我的主列表中有 60,000 个子列表,那么是否有针对此的矢量化解决方案?

提前致谢。

【问题讨论】:

  • 我不明白您是如何从列表示例列表 a 变成翻过来的列表,也称为 a。还是它们之间没有关系?
  • 很简单:从 1 到 max(a[1..3]) 形成的新列表的名称,值是旧列表的名称/索引,其中新名称作为值找到。例如。值 1 在所有子列表中都不存在,所以它是 NULL,值 2 仅在子列表 a[[1]] 中找到,值 6 在所有 a[[1]]a[[2]]a[[3]] 中找到,sot(新)@987654332 @ 包含 c(1, 2, 3)
  • 是的,这就是我想要的

标签: r list


【解决方案1】:

这是一个基本的 R 方式。

lapply(seq.int(max(unique(unlist(a)))), \(i){
  which(sapply(a, \(x) any(i == x)))
})

【讨论】:

  • @maydin 你是对的,谢谢。当您发布评论时,我正在纠正错误。
  • 非常好的编码方式!能简单解释一下\(i)\(x)的用法吗?
  • @JKupzig 第一个循环变量i 循环遍历列表的所有唯一元素,第二个变量x 是每个列表成员(每个向量),用于检查i 是否为在那个向量中。
  • 非常感谢。嵌套的应用函数起到了作用。
  • 感谢@RuiBarradas 的解释
【解决方案2】:

另一种方式:

 searchInList <- function(list2search, e){
      idx2search <- 1:length(list2search)
      list2search2 <- lapply(list2search, `length<-`, max(lengths(list2search)))
      output <- matrix(unlist(list2search2), ncol = length(list2search2[[1]]), byrow = TRUE)
      idx <- apply(output, 1, function(x){ (e %in% x) } )
      return(idx2search[idx])
    }

result <- lapply(1:max(unlist(a)), function(x) { searchInList(a, x) } )

【讨论】:

    【解决方案3】:

    这是使用matchrapply 的一种方式。

    apply(matrix(rapply(a, \(x) !is.na(match(1:max(unlist(a)), x))),,length(a)), 1, which)
    # [[1]]
    # integer(0)
    # 
    # [[2]]
    # [1] 1
    # 
    # [[3]]
    # [1] 1
    # 
    # [[4]]
    # [1] 1 2
    # 
    # [[5]]
    # [1] 1 2
    # 
    # [[6]]
    # [1] 1 2 3
    # 
    # [[7]]
    # [1] 1 2 3
    # 
    # [[8]]
    # [1] 2 3
    # 
    # [[9]]
    # [1] 3
    # 
    # [[10]]
    # [1] 3
    

    【讨论】:

      【解决方案4】:

      使用基础 R 的另一种解决方案:

      apply(sapply(a, `%in%`, x = seq_len(max(unlist(a)))), 1, which)
      

      【讨论】:

        【解决方案5】:

        tidyverse 方法:

        library(purrr)
        a <- list(c(2, 3, 4, 5, 6, 7), c(4, 5, 6, 7, 8), c(6, 7, 8, 9, 10))
        
        i = 1:10
        map(i, ~map_int(imap(a, ~(..3 %in% .x)*.y, i), ~.x[.y], .x) %>% .[. != 0])
        

        逻辑是获取TRUE 值的位置列表,并将其与列表元素索引相乘。这里,第一个向量的第一个元素,第二个向量的第一个元素,第三个向量的第三个元素都匹配,因此目标列表中的第一个元素。

        imap(a, ~(..3 %in% .x)*.y, i)
        [[1]]
         [1] 0 1 1 1 1 1 1 0 0 0
        
        [[2]]
         [1] 0 0 0 2 2 2 2 2 0 0
        
        [[3]]
         [1] 0 0 0 0 0 3 3 3 3 3
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-18
          • 2013-10-14
          相关资源
          最近更新 更多