【问题标题】:How to turn a list inside out?如何将列表翻转过来?
【发布时间】:2019-06-07 13:36:38
【问题描述】:

我有以下列表:

> list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7))
[[1]]
[1] 3 4 5 8

[[2]]
[1]  2  6  9 10

[[3]]
[1] 1 7

所以我们可以说 3 属于第 1 组,6 属于第 2 组,7 属于第 3 组,依此类推。我需要一个反向映射,即我想要拥有一个属于它的组 id 的每个数字(参见预期输出):

> list(3, 2, 1, 1, 1, 2, 3, 1, 2, 2)
[[1]]
[1] 3

[[2]]
[1] 2

[[3]]
[1] 1

[[4]]
[1] 1

[[5]]
[1] 1

[[6]]
[1] 2

[[7]]
[1] 3

[[8]]
[1] 1

[[9]]
[1] 2

[[10]]
[1] 2

我认为purrr::transpose 应该完成这项工作,但它并不完全符合我的意图,是吗?如何做呢?

PS。最终,我只需要一个形式的向量:3 2 1 1 1 2 3 1 2 2,但我认为unlist() 足以转换。

【问题讨论】:

  • 我很抱歉,但我不知道如何从给定的输入中获取3 2 1 1 1 2 3 1 2 2,至少我不清楚。谢谢
  • @PKumar: 1 在第 3 组,2 在第 2 组,3 在第 1 组,4 在第 1 组,5 在第 1 组 ...
  • 我们从 1 开始,看看 1 属于哪个组 - 我们可以看到它在第 3 组,即列表的第 3 个元素。然后我们在 2:10 进行检查。

标签: r base purrr


【解决方案1】:

这是一个基本的解决方案...

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

rep(1:length(list), sapply(list, length))[order(unlist(list))]

【讨论】:

  • 不错的解决方案,您可以使用rep(seq_along(l), lengths(l))[order(unlist(l))] 完全矢量化它(不确定您使用as.numeric 做什么)。
  • 关于“列表转换不能完全回答我的主要问题”我认为你需要澄清你的问题。您描述和呈现所需结果的方式似乎只是想获取每个值的列表索引(这个和其他答案都可以实现)。我看不到“由内而外”的部分;)
  • @DavidArenburg 好点(原始解决方案有点长,所以这只是剩下的噪音;-))
【解决方案2】:

我能推荐一个老式的循环吗:

# your list
x <- list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7))
# the data in the list as vector
num <- unlist( x )
# the variable that will be the position vector
pos <- NULL

# loop through the possible position, see which number it contains
# find which "group it belongs to, and add that finding to the position vector
for( i in 1:length( num ) )
    for( j in  1:length( x ) )
        if( i %in% x[[j]] ) pos <- c( pos, j )

pos
[1] 3 2 1 1 1 2 3 1 2 2

【讨论】:

    【解决方案3】:

    检查这个解决方案:

    library(tidyverse)
    library(magrittr)
    library(wrapr)
    
    list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7)) %.>%
      tibble(x = .) %>%
      mutate(rn = row_number()) %>%
      unnest() %>%
      arrange(x) %$%
      set_names(rn, x) %>%
      as.list()
    

    【讨论】:

    • 第5行是不是写错了%.&gt;%
    • 没有。这是来自wrapr 包的管道。
    • 为什么你在 wrapr 中额外使用 %.&gt;% 而不是在 tidyverse 中使用 %&gt;%?在这种情况下,他们将得到相同的结果。
    【解决方案4】:
    x <- list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7))
    

    以下 3 种形式将得到相同的输出:

    library(tidyverse)
    
    # (1)
    x %>% set_names(1:3) %>% stack %>% arrange(values) %>% select(ind)
    
    # (2)
    x %>% enframe %>% unnest %>% arrange(value) %>% select(name)
    
    # (3)
    x %>% (reshape2::melt) %>% arrange(value) %>% select(L1)
    

    【讨论】:

      【解决方案5】:

      同样在base,类似这样的

      L <- as.list(setNames( rep(1:length(lengths(l)), lengths(l)), unlist(l)))
      # if wanted, sort it with
      L[as.character(sort(as.integer(names(L))))]
      # if wanted, unname with
      unname(L)
      

      l &lt;- list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7))

      或者包裹在一个函数中

      list_inside_out <- function (l, unName = TRUE) { 
        l2 <- lengths(l)
        out <- as.list(setNames(rep(1:length(l2), l2), unlist(l)))
        out <- out[as.character(sort(as.integer(names(out))))] 
        if (unName) return(unname(out))
        out
      }
      list_inside_out(l)
      # [[1]]
      # [1] 3
      # 
      # [[2]]
      # [1] 2
      # 
      # [[3]]
      # [1] 1
      # ...
      

      【讨论】:

        【解决方案6】:

        使用purrr 的解决方案。 dat2 是最终输出,一个整数向量。

        dat <- list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7))
        
        library(purrr)
        
        dat2 <- dat %>%
          imap(~set_names(.x, rep(.y, length(.x)))) %>%
          unlist() %>%
          sort() %>%
          names() %>%
          as.integer()
        dat2
        # [1] 3 2 1 1 1 2 3 1 2 2
        

        【讨论】:

          【解决方案7】:

          使用 tidyversepurr::imap_dfr 我们可以创建一个 tibble 并列的值和索引,arrange 按值和pull 索引:

          list_ <- list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7))
          library(tidyverse)
          imap_dfr(list_,~tibble(.x,.y)) %>% arrange(.x) %>% pull(.y) %>% as.list
          
          # [[1]]
          # [1] 3
          # 
          # [[2]]
          # [1] 2
          # 
          # [[3]]
          # [1] 1
          # 
          # [[4]]
          # [1] 1
          # 
          # [[5]]
          # [1] 1
          # 
          # [[6]]
          # [1] 2
          # 
          # [[7]]
          # [1] 3
          # 
          # [[8]]
          # [1] 1
          # 
          # [[9]]
          # [1] 2
          # 
          # [[10]]
          # [1] 2
          

          在基础 R 中的翻译不太漂亮(相同的输出):

          with(
            as.data.frame(do.call(rbind,Map(cbind,a = list_, b =seq_along(list_)))),
            as.list(b[order(a)]))
          

          【讨论】:

            猜你喜欢
            • 2010-12-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-11-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-11-14
            相关资源
            最近更新 更多