代码之家  ›  专栏  ›  技术社区  ›  jakes

如何把清单翻出来?

  •  8
  • jakes  · 技术社区  · 6 年前

    我有以下清单:

    > 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 应该做这项工作,但它并不完全符合我的意愿,是吗?怎样才能做到呢?

    最后,我只需要一个形式的向量: 3 2 1 1 1 2 3 1 2 2 ,但我认为 unlist() 足以改变信仰。

    7 回复  |  直到 6 年前
        1
  •  3
  •   Khaynes    6 年前

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

    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))]
    
        2
  •  2
  •   vaettchen    6 年前

    我能建议一个老式的循环:

    # 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
  •  1
  •   Paweł Chabros    6 年前

    检查此解决方案:

    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()
    
        4
  •  1
  •   Darren Tsai    6 年前
    x <- list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7))
    

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

    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
  •  1
  •   niko    6 年前

    也在 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 <- 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
  •  0
  •   www    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
  •  0
  •   moodymudskipper    6 年前

    使用 tidyverse purr::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)]))