从列表中查找唯一值

Rom*_*rik 28 r list unique

假设您有一个值列表

x <- list(a=c(1,2,3), b = c(2,3,4), c=c(4,5,6))
Run Code Online (Sandbox Code Playgroud)

我想找到所有列表元素组合的唯一值.到目前为止,以下代码完成了这一操作

unique(unlist(x))
Run Code Online (Sandbox Code Playgroud)

有谁知道更有效的方式?我有一个很有价值的大量清单,并会欣赏任何加速.

Rei*_*son 42

Marek建议的这个解决方案是对原始Q的最佳答案.请参阅下面的讨论其他方法以及为什么Marek最有用.

> unique(unlist(x, use.names = FALSE))
[1] 1 2 3 4 5 6
Run Code Online (Sandbox Code Playgroud)

讨论

更快的解决方案是计算unique()您的x第一个组件,然后unique()对这些结果进行最终决策.这仅在列表的组件具有相同数量的唯一值时才有效,如下面两个示例中所示.例如:

首先是你的版本,然后我的双重独特方法:

> unique(unlist(x))
[1] 1 2 3 4 5 6
> unique.default(sapply(x, unique))
[1] 1 2 3 4 5 6
Run Code Online (Sandbox Code Playgroud)

我们必须打电话,unique.default因为有一种matrix方法unique可以保持一个保证金固定; 这很好,因为矩阵可以被视为一个向量.

马雷克在对这个答案的评论中指出,该unlist方法的缓慢速度可能是由于names列表上的.Marek的解决方案是利用use.names参数unlist,如果使用的话,会产生比上面的双独特版本更快的解决方案.对于xRoman的帖子我们得到的简单

> unique(unlist(x, use.names = FALSE))
[1] 1 2 3 4 5 6
Run Code Online (Sandbox Code Playgroud)

即使组件之间的独特元素数量不同,Marek的解决方案也能正常工作.

这是一个更大的例子,包含所有三种方法的一些时间:

## Create a large list (1000 components of length 100 each)
DF <- as.list(data.frame(matrix(sample(1:10, 1000*1000, replace = TRUE), 
                                ncol = 1000)))
Run Code Online (Sandbox Code Playgroud)

以下是使用DF以下两种方法的结果:

> ## Do the three approaches give the same result:
> all.equal(unique.default(sapply(DF, unique)), unique(unlist(DF)))
[1] TRUE
> all.equal(unique(unlist(DF, use.names = FALSE)), unique(unlist(DF)))
[1] TRUE
> ## Timing Roman's original:
> system.time(replicate(10, unique(unlist(DF))))
   user  system elapsed 
  12.884   0.077  12.966
> ## Timing double unique version:
> system.time(replicate(10, unique.default(sapply(DF, unique))))
   user  system elapsed 
  0.648   0.000   0.653
> ## timing of Marek's solution:
> system.time(replicate(10, unique(unlist(DF, use.names = FALSE))))
   user  system elapsed 
  0.510   0.000   0.512
Run Code Online (Sandbox Code Playgroud)

这表明双倍unique应用于unique()单个组件然后unique()是那些较小的独特值集更快,但这种加速纯粹是由于names列表上的DF.如果我们告诉unlist不要使用names,马立克的解决方案比unique这个问题的双倍快.由于Marek的解决方案正确使用了正确的工具,并且比解决方案更快,因此它是首选解决方案.

与双大疑难杂症unique的办法是,它只会工作,如果,作为两个例子在这里,输入列表(的每个部件DFx)具有相同数量的唯一值.在这种情况下,sapply将结果简化为允许我们应用的矩阵unique.default.如果输入列表的组件具有不同数量的唯一值,则双唯一解决方案将失败.

  • @ucfagls你的意思是`unique(unlist(DF,use.names = FALSE))`` 如果你愿意,请把它包括在你的答案中;) (2认同)