如何在R中的嵌套列表中获取元素的并集

时间:2011-04-25 05:34:59

标签: r

我在lst中有一个嵌套列表(所有元素都是类int)。我事先并不知道lst的长度;但我知道lst的每个元素都是长度为k

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

如何获取union的所有元素的第1个元素,第2个元素,...,第k个元素的lst

具体来说,如果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")))

5 个答案:

答案 0 :(得分:4)

这是一个通用解决方案,与@Ramnath的精神相似,但避免使用union()这是一个二元函数。诀窍是要注意union()实现为:

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

可以通过取消列出每个列表的unique()组件来实现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

您显示的数据。

这方面的一些有用功能是:

  • 我们在`[[`中使用objunionFun的子集。这与@ Ramnath的答案中的function(x) x$a相似。但是,我们不需要匿名函数(我们使用`[[`代替)。相当于@ Ramnath的答案是:lapply(lst, `[[`, 1)
  • 概括上述内容,我们将上面的1替换为n中的unionFun(),并允许我们的列表作为参数obj传递。

现在我们有一个函数可以提供给定列表的n个元素的并集,我们可以lapply()覆盖索引k,应用我们的unionFun() lst的每个子元素使用lst[[1]]的长度与所有length(lst[[k]])的{​​{1}}相同的事实。

如果在返回的对象中包含k元素的名称有帮助,我们可以这样做:

n

答案 1 :(得分: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)

如果列表中包含的元素超过2个,我们可以对此代码进行概括。

答案 2 :(得分:2)

以下是另一种方法:使用do.call/rbind按“名称”将列表排列到数据框中,然后将apply unique/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

答案 3 :(得分: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

但是,嵌套结构不是非常用户友好。这可能会有所改变......

答案 4 :(得分:0)

根据文件&#34;取消列出&#34;是一个递归函数,因此无论提供的列表的嵌套级别如何,您都可以通过将它们传递给unlist来获取所有元素。您可以按如下方式获取子列表的并集。

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