2017-09-27 75 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