2011-04-25 40 views
4

我有一個嵌套列表,如lst(所有元素都是int)。我不知道提前lst的長度;然而,我知道的lst每個元素是長的名單說k如何在R中嵌套列表中使用元素的並集

length(lst[[i]]) # this equals k and is known in advance, 
       # this is true for i = 1 ... length(lst) 

我怎麼拿第一元素,第二個元素,...,的lst

所有元素的第k個元素的 union

具體而言,如果lst長度n,我想(不屬於R代碼):

# I know that union can only be taken for 2 elements, 
# following is for illustration purposes 
listUnion1 <- union(lst[[1, 1]], lst[[2, 1]], ..., lst[[n, 1]]) 
listUnion2 <- union(lst[[1, 2]], lst[[2, 2]], ..., lst[[n, 2]]) 
. 
. 
. 
listUnionk <- union(lst[[1, k]], lst[[2, k]], ..., lst[[n, k]]) 

任何幫助或指針不勝感激。

這裏是可以使用的數據集,N = 3和K = 2

list(structure(list(a = 1:5, b = 6:11), .Names = c("a", "b")), 
    structure(list(a = 6:11, b = 1:5), .Names = c("a", "b")), 
    structure(list(a = 12, b = 12), .Names = c("a", "b"))) 
+0

如果問題不清楚或存在問題,請讓我知道。請提前接受我誠摯的歉意。 – suncoolsu 2011-04-25 05:35:47

+0

唯一讓我感到困惑的是你的符號'lst [[1,1]]'這是你顯示的列表不正確的R代碼。我知道你說它不是R代碼,但是'lst [[1]] [1]'會更好,因爲它是R代碼。另一件有用的東西就是你提供的示例數據的一些示例輸出(順便說一下,謝謝!)。除此之外,我認爲Q很有趣。 – 2011-04-25 12:15:39

+0

@gavin感謝您的解決方案。對不起,我應該小心! – suncoolsu 2011-04-25 13:44:07

回答

4

這裏是一個通用的解決方案,在精神上類似@Ramnath,但避免使用union()這是一個二元函數。關鍵是要注意的是union()被實現爲:

unique(c(as.vector(x), as.vector(y))) 

和內部unique()位可以通過unlisting每個列表的n個分量來實現。然後

完整的解決方案是:

unionFun <- function(n, obj) { 
    unique(unlist(lapply(obj, `[[`, n))) 
} 
lapply(seq_along(lst[[1]]), FUN = unionFun, obj = lst) 

這給:

[[1]] 
[1] 1 2 3 4 5 6 7 8 9 10 11 12 

[[2]] 
[1] 6 7 8 9 10 11 1 2 3 4 5 12 
你顯示數據

一對夫婦的這個有用的特點是:

  • 我們使用`[[`unionFun於子集obj。這與@ Ramnath的答案中的function(x) x$a類似。但是,我們不需要匿名函數(我們使用`[[`代替)。相當於@ Ramnath的回答是:lapply(lst, `[[`, 1)
  • 概括上面,我們在更換1以上的unionFun()n,並允許通過我們的列表作爲參數obj

現在,我們有一個功能,將提供一個給定的列表的n個元素的結合,我們可以lapply()在指數k,運用我們unionFun()lst每個子元素,使用的事實,所有k的長度爲lst[[1]]length(lst[[k]])相同。

如果它有助於在返回的對象n個元素的名稱,我們可以這樣做:

> unions <- lapply(seq_along(lst[[1]]), FUN = unionFun, obj = lst) 
> names(unions) <- names(lst[[1]]) 
> unions 
$a 
[1] 1 2 3 4 5 6 7 8 9 10 11 12 

$b 
[1] 6 7 8 9 10 11 1 2 3 4 5 12 
+0

真棒 - 非常有幫助!有像你這樣的人花時間解釋他們的解決方案真是太棒了。 – suncoolsu 2011-04-25 13:49:10

3

這裏是一個解決方案

# generate dummy data 
x1 = sample(letters[1:5], 20, replace = T) 
x2 = sample(letters[1:5], 20, replace = T) 
df = data.frame(x1, x2, stringsAsFactors = F) 

# find unique elements in each column 
union_df = apply(df, 2, unique) 

讓我知道這是否正常工作

編輯:以下是使用您提供的數據的清單解決方案

mylist = list(structure(list(a = 1:5, b = 6:11), .Names = c("a", "b")), 
       structure(list(a = 6:11, b = 1:5), .Names = c("a", "b")), 
       structure(list(a = 12, b = 12), .Names = c("a", "b"))) 
list_a = lapply(mylist, function(x) x$a) 
list_b = lapply(mylist, function(x) x$b) 

union_a = Reduce(union, list_a) 
union_b = Reduce(union, list_b) 

如果您的列表中有兩個以上的元素,我們可以推廣此代碼。

+0

謝謝,我會非常感興趣的解決方案,使用*應用功能,除了適用(因爲它就像使用for循環)。此外df似乎不是列表的列表? – suncoolsu 2011-04-25 06:16:53

+0

@suncoolsu看看我編輯的解決方案列表 – Ramnath 2011-04-25 06:33:14

+0

謝謝你的解決方案!我會接受加文的解決方案,因爲它概括了你的想法。 – suncoolsu 2011-04-25 13:55:28

1

你的數據

df <- list(structure(list(a = 1:5, b = 6:11), .Names = c("a", "b")), 
      structure(list(a = 6:11, b = 1:5), .Names = c("a", "b")), 
      structure(list(a = 12, b = 12), .Names = c("a", "b"))) 

這使您可以嵌套列表的獨特價值:

library(plyr) 
df.l <- llply(df, function(x) unlist(unique(x))) 

R> df.l 
[[1]] 
[1] 1 2 3 4 5 6 7 8 9 10 11 

[[2]] 
[1] 6 7 8 9 10 11 1 2 3 4 5 

[[3]] 
[1] 12 

編輯

感謝Ramnath我改變了代碼一點,希望這答案符合你的問題的需要。爲了說明,我保留以前的答案。稍有變化的數據現在有一個額外的列表。

df <- list(structure(list(a = 1:5, b = 6:11), .Names = c("a", "b")), 
      structure(list(a = 6:11, b = 1:5), .Names = c("a", "b")), 
      structure(list(a = 12, b = 12, c = 10:14), .Names = c("a", "b", "c"))) 


f.x <- function(x.list) { 
    x.names <- names(x.list) 
    i <- combn(x.names, 2) 
    l <- apply(i, 2, function(y) x.list[y]) 
    llply(l, unlist) 
} 

現在您可以將該函數應用於您的數據。

all.l <- llply(df, f.x) 
llply(all.l, function(x) llply(x, unique)) 

R> [[1]] 
[[1]][[1]] 
[1] 1 2 3 4 5 6 7 8 9 10 11 


[[2]] 
[[2]][[1]] 
[1] 6 7 8 9 10 11 1 2 3 4 5 


[[3]] 
[[3]][[1]] 
[1] 12 

[[3]][[2]] 
[1] 12 10 11 13 14 

[[3]][[3]] 
[1] 12 10 11 13 14 

但是,嵌套結構不是非常用戶友好。這可能會改變一點...

+0

我認爲OP希望所有列表的第k個元素的聯合。你的解決方案返回每個列表中所有元素的聯合。你可能想修改你的plyr電話 – Ramnath 2011-04-25 06:57:20

+0

@Ramnath Thanks Ramnath,我改變了一下。並留下一些空間,以獲得更多改進;-) – mropa 2011-04-25 08:18:18

2

這裏的另一種方式:使用do.call/rbind由「名」列表排隊到數據 - 幀,然後applyunique/do.call到這個數據幀的每一列。 (我稍微修改了你的數據,所以'a'和'b'聯盟的長度不同,以確保它能正常工作)。

lst <- list(structure(list(a = 1:5, b = 6:11), .Names = c("a", "b")), 
    structure(list(a = 6:10, b = 1:5), .Names = c("a", "b")), 
    structure(list(a = 12, b = 12), .Names = c("a", "b"))) 

> apply(do.call(rbind, lst),2, function(x) unique(do.call(c, x))) 
$a 
[1] 1 2 3 4 5 6 7 8 9 10 12 

$b 
[1] 6 7 8 9 10 11 1 2 3 4 5 12 
+0

這是一個不錯的解決方案@Prasad。 'do.call'位返回一個有趣的對象。 – 2011-04-25 13:52:33

+0

@Gavin,謝謝...是的,第一個do.call返回一個奇怪的數據框,其元素是列表。 – 2011-04-25 14:24:27

0

根據該文件「不公開」是一個遞歸函數,因此,無論提供你可以通過它們來獲得不公開所有元素的列表的嵌套級別。您可以按如下方式獲得子列表的聯合。

lst <- list(structure(list(a = 1:5, b = 6:11), .Names = c("a", "b")), 
structure(list(a = 6:11, b = 1:5), .Names = c("a", "b")), 
structure(list(a = 12, b = 12), .Names = c("a", "b"))) 

lapply(lst, function(sublst) unique(unlist(sublst))) 

[[1]] 
[1] 1 2 3 4 5 6 7 8 9 10 11 

[[2]] 
[1] 6 7 8 9 10 11 1 2 3 4 5 

[[3]] 
[1] 12