List 从列表中查找唯一值

List 从列表中查找唯一值,list,r,unique,List,R,Unique,假设您有一个值列表 x <- list(a=c(1,2,3), b = c(2,3,4), c=c(4,5,6)) 有人知道更有效的方法吗?我有一个包含很多值的庞大列表,如果能加快速度,我将不胜感激。马立克提出的这个解决方案是对原始问题的最佳答案。有关其他方法以及为什么马立克的方法最有用的讨论,请参见下文 > unique(unlist(x, use.names = FALSE)) [1] 1 2 3 4 5 6 讨论 一个更快的解决方案是首先对x的组件计算unique(),然

假设您有一个值列表

x <- list(a=c(1,2,3), b = c(2,3,4), c=c(4,5,6))

有人知道更有效的方法吗?我有一个包含很多值的庞大列表,如果能加快速度,我将不胜感激。

马立克提出的这个解决方案是对原始问题的最佳答案。有关其他方法以及为什么马立克的方法最有用的讨论,请参见下文

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

讨论 一个更快的解决方案是首先对
x
的组件计算
unique()
,然后对这些结果执行最后的
unique()
。只有当列表的组件具有相同数量的唯一值时,这才会起作用,就像下面两个示例中一样。例如:

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

> unique(unlist(x))
[1] 1 2 3 4 5 6
> unique.default(sapply(x, unique))
[1] 1 2 3 4 5 6
我们必须调用
unique.default
,因为
unique
有一个
matrix
方法保持一个边距固定;这很好,因为矩阵可以被视为向量

马雷克在对这一回答的评论中指出,
unlist
方法的速度缓慢可能是由于列表上的
名称。Marek的解决方案是使用
use.names
参数来
unlist
,如果使用该参数,将产生比上述双唯一版本更快的解决方案。对于罗曼的简单的
x
,我们得到

> unique(unlist(x, use.names = FALSE))
[1] 1 2 3 4 5 6
即使组件之间的唯一元素数量不同,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)))
这表明双
unique
比将
unique()
应用于单个组件,然后将
unique()
应用于较小的唯一值集要快得多,但这种加速纯粹是由于
DF
列表中的
名称。如果我们告诉
unlist
不要使用
名称
,那么对于这个问题,Marek的解决方案比double
unique
稍微快一些。由于Marek的解决方案正确使用了正确的工具,并且比解决方案更快,因此它是首选解决方案


unique
方法的一个大问题是,只有在的情况下,它才会起作用,就像在这里的两个示例中一样,输入列表的每个组件(
DF
x
)具有相同数量的唯一值。在这种情况下,
sapply
将结果简化为一个矩阵,允许我们应用
unique.default
。如果输入列表的组件具有不同数量的唯一值,则双唯一解决方案将失败。

检查
system.time(复制(10,唯一(未列出(DF,FALSE,FALSE)))
。它更快,就是这样。您只需要
unique(unlist(DF,use.names=TRUE))
就可以大幅提高速度。我知道数据帧上的名称是速度减慢的一个原因,但我没有想到这会是一个问题。就我所见,没有任何递归作为
DF
x
只包含一个级别的组件。你应该把它作为一个答案,因为它直接使用了正确的工具。从47秒提高到0.05秒。我认为这很重要@ucfagls您的意思是
唯一(未列出(DF,use.names=FALSE))
?如果您喜欢,请在您的答案中包含它;)@马瑞克:哦,是的,我的意思是
唯一(unlist(DF,use.names=FALSE))
。将通过适当的归因为我的答案添加您的改进。
## 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)))
> ## 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