2014-03-06 111 views
6

我有一個向量列表(如下所示)。我想知道向量的每個元素在哪個列表元素中。換句話說,我想反轉列表以創建一個新列表,其中names取自矢量。元素作爲列表名稱和列表名稱作爲列表中的元素?

這樣做的最佳方法是什麼?

lst <- list(a=c(2, 3, 6, 10, 15, 17), b=c(4, 6, 9, 7, 6, 4, 3, 10), 
      c=c(9, 2, 1, 4, 3), d=c(3, 6, 17)) 
lst 
$a 
[1] 2 3 6 10 15 17 

$b 
[1] 4 6 9 7 6 4 3 10 

$c 
[1] 9 2 1 4 3 

$d 
[1] 3 6 17 

我想獲得以下答案。

$`1` 
[1] "c" 

$`10` 
[1] "a" "b" 

$`15` 
[1] "a" 

$`17` 
[1] "a" "d" 

$`2` 
[1] "a" "c" 

$`3` 
[1] "a" "b" "c" "d" 

$`4` 
[1] "b" "b" "c" 

$`6` 
[1] "a" "b" "b" "d" 

$`7` 
[1] "b" 

$`9` 
[1] "b" "c" 

回答

8

這裏有一個基地R的方式與stackunstack

unstack(stack(lst), ind ~ values) 
# $`1` 
# [1] "c" 
# 
# $`2` 
# [1] "a" "c" 
# 
# $`3` 
# [1] "a" "b" "c" "d" 
# 
# $`4` 
# [1] "b" "b" "c" 
# 
# $`6` 
# [1] "a" "b" "b" "d" 
# 
# $`7` 
# [1] "b" 
# 
# $`9` 
# [1] "b" "c" 
# 
# $`10` 
# [1] "a" "b" 
# 
# $`15` 
# [1] "a" 
# 
# $`17` 
# [1] "a" "d" 
+1

聰明地使用'unstack'。 +1 – A5C1D2H2I1M1N2O1R2T1

+0

@Matthew謝謝。它工作和簡單。 – BioChemoinformatics

+0

我不太明白'lapply(lst,as.vector)'的含義。至少在這個例子中,你可以用lst代替,沒有什麼會改變。 – Dason

6

下面是使用split從基礎R的方法使用melt從 「reshape2」 之後:

library(reshape2) 
x <- melt(lst) 
split(x$L1, x$value) 
# $`1` 
# [1] "c" 
# 
# $`2` 
# [1] "a" "c" 
# 
# $`3` 
# [1] "a" "b" "c" "d" 
# 
# $`4` 
# [1] "b" "b" "c" 
# 
# $`6` 
# [1] "a" "b" "b" "d" 
# 
# $`7` 
# [1] "b" 
# 
# $`9` 
# [1] "b" "c" 
# 
# $`10` 
# [1] "a" "b" 
# 
# $`15` 
# [1] "a" 
# 
# $`17` 
# [1] "a" "d" 

同樣,在基礎R與stack

x <- stack(lapply(lst, c)) 
split(as.character(x$ind), x$values) 

甚至如果您使用「lst」而不是「lst」,則更直接:

x <- stack(lst) 
split(as.character(x$ind), x$values) 

要闡述我的意見,我被介紹給更有效的方式是:

split(rep(names(lst), lapply(lst, nrow)), unlist(lst, use.names = FALSE)) 

應用到一個更大的lst,我們得到如下:

fun1 <- function() split(rep(names(lst), lapply(lst, nrow)), unlist(lst, use.names = FALSE)) 
fun2 <- function() { x <- stack(lapply(lst, c)) ; split(as.character(x$ind), x$values) } 
fun3 <- function() { x <- melt(lst) ; split(x$L1, x$value) } 
fun4 <- function() unstack(stack(lapply(lst, as.vector)), ind ~ values) 

## Make lst much bigger 
lst <- unlist(replicate(10000, lst, simplify = FALSE), recursive=FALSE) 
names(lst) <- make.unique(names(lst)) 

library(microbenchmark) 

system.time(fun3()) 
# user system elapsed 
# 48.338 0.000 47.643 

microbenchmark(fun1(), fun2(), fun4(), times = 5) 
# Unit: milliseconds 
# expr  min  lq median  uq  max neval 
# fun1() 454.5913 456.6793 473.901 555.8954 574.4394  5 
# fun2() 922.1282 1028.4972 1034.872 1068.4761 1150.8072  5 
# fun4() 1222.5296 1300.0643 1323.253 1339.2037 1421.1546  5 
+0

嗨阿南達,謝謝。有用。但是,如果列表1非常大,「融化」看起來速度稍低一點,對吧?你有更有效的方法嗎? – BioChemoinformatics

+0

@Kevin,'stack'應該比'melt'快,或者你可以使用'rep'和'unlist'。 – A5C1D2H2I1M1N2O1R2T1

+0

謝謝阿南達。你的答案是我想要的。 – BioChemoinformatics

0

unlistlist獲得矢量中的所有數字。然後,使用這些數字拆分list元素的names的向量。

split(rep(names(lst),times=sapply(lst,length)), 
     unlist(lst)) 
$`1` 
[1] "c" 

$`2` 
[1] "a" "c" 

$`3` 
[1] "a" "b" "c" "d" 

$`4` 
[1] "b" "b" "c" 

$`6` 
[1] "a" "b" "b" "d" 

$`7` 
[1] "b" 

$`9` 
[1] "b" "c" 

$`10` 
[1] "a" "b" 

$`15` 
[1] "a" 

$`17` 
[1] "a" "d" 
+0

這與我的回答非常相似,但是使用'length'而不是'nrow'(這是您的問題的原始版本的正確答案)。 – A5C1D2H2I1M1N2O1R2T1

+0

代碼是一樣的,但我更喜歡這個演示。我應該更徹底地閱讀你的答案。直到我發佈我的答案後,我才找到'fun1'。儘管這並不重要,但你更全面的答案應該有更多的選票,並且會保持在最高位置。 – kdauria

+0

對不起,如果這是令人困惑,但我不是同一個「凱文」誰發佈的問題。我編輯了原始問題,因爲我很難閱讀。 – kdauria

相關問題