我有一个清单:
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个对象)。
答案 0 :(得分:5)
您可以按相反的顺序在列表中使用Reduce
和setdiff
,以查找最后一个矢量中未出现在其他元素中的所有元素。将其加入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
之外作为新变量,以及其中的子集。< / p>
答案 1 :(得分: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)
并在每一步将prev
变为c(prev,x[i-1])
来改善这一点(尽管这会在每一步增加一个向量,这是一个运行缓慢)。如果您没有庞大的数据集/不必进行数百万次此操作,那么它可能已经足够好了。