2017-09-27 66 views
1

我有一个列表:如何删除共享值

x <- list("a" = c(1:6,32,24) , "b" = c(1:4,8,10,12,13,17,24), 
      "F" = c(1:5,9:15,17,18,19,20,32)) 
x 

$a 
[1] 1 2 3 4 5 6 32 24 

$b 
[1] 1 2 3 4 8 10 12 13 17,24 

$F 
[1] 1 2 3 4 5 9 10 11 12 13 14 15 17 18 19 20 32 

列表中的每个向量共享一个号码与他人元件。我如何删除共享值以获得以下结果?

$a 
    [1] 1 2 3 4 5 6 32 24 

    $b 
    [1] 8 10 12 13 17 

    $F 
    [1] 9 11 14 15 18 19 20 

正如你所看到的:第一个向量不会改变。第一个和第二个向量之间的共享元素将从第二个向量中移除,然后我们将第三个向量与第一个和第二个向量进行比较之后,从第三个向量中移除共享元素。此任务的目标是聚类数据集(原始数据集包含590个对象)。

回答

1
x <- list("a" = c(1:6,32,24) , 
      "b" = c(1:4,8,10,12,13,17,24), 
      "F" = c(1:5,9:15,17,18,19,20,32)) 

这是低效的,因为它重新使前一组列表中的工会 在每一步(而不是 保持运行总计),但它是我想到的第一 方式。

for (i in 2:length(x)) { 
    ## construct union of all previous lists 
    prev <- Reduce(union,x[1:(i-1)]) 
    ## remove shared elements from the current list 
    x[[i]] <- setdiff(x[[i]],prev) 
} 

你也许可以通过初始化prev作为numeric(0),使prevc(prev,x[i-1])在每一步(虽然这种增长在每一个步骤,这是一个缓慢的操作的矢量)改进这一点。如果你没有一个巨大的数据集/不必做数百万次这个操作就可能足够好。

5

,可以在列表上使用Reducesetdiff相反的顺序来查找不会出现在其他人的最后一个向量的所有元素。蓬此为lapply超过部分子列表运行得到你想要的输出:

lapply(seq_along(x), function(y) Reduce(setdiff,rev(x[seq(y)]))) 
[[1]] 
[1] 1 2 3 4 5 6 32 24 

[[2]] 
[1] 8 10 12 13 17 

[[3]] 
[1] 9 11 14 15 18 19 20 

当扩大的rev呼叫的数量可能会成为一个问题,所以你可能要一次扭转列表中,外作为新变量的lapply以及其中的子集。

+0

x_rev < - rev(x); lapply(seq_along(x),function(y)Reduce(setdiff,x_rev [seq(y)]))...会根据您的评论给出不同的结果。反正+1。你的解决方案是一个真正的美。 –

+0

谢谢,詹姆斯为你的答案,它完美的作品。 – Noor

+0

@AndreElrico好点,你必须注意索引。我认为'tail(x_rev,y)'会效果最好。 – James