我有一个数字向量列表,我需要创建一个只包含每个向量的一个副本的列表.对于相同的函数没有列表方法,所以我写了一个函数来应用来检查每个向量对齐.
F1 <- function(x){ to_remove <- c() for(i in 1:length(x)){ for(j in 1:length(x)){ if(i!=j && identical(x[[i]],x[[j]]) to_remove <- c(to_remove,j) } } if(is.null(to_remove)) x else x[-c(to_remove)] }
问题在于,由于输入列表x的大小增加,这个函数变得非常慢,这部分是由于for循环分配了两个大的向量.我希望能够在一分钟内运行长度为150万的长度为15的向量的方法,但这可能是乐观的.
有没有人知道一个更有效的方法来比较列表中的每个向量与每个其他向量?载体本身的长度保证相等.
样品输出如下所示.
x = list(1:4,1:4,2:5,3:6) F1(x) > list(1:4,3:6)
解决方法
根据@JoshuaUlrich和@thelatemail,ll [!duplicate(ll)]工作正常.
因此,所以应该是唯一的(ll)
我以前建议一个方法使用sapply的想法,不检查列表中的每个元素(我删除了那个答案,因为我认为使用独特的更有意义)
因此,所以应该是唯一的(ll)
我以前建议一个方法使用sapply的想法,不检查列表中的每个元素(我删除了那个答案,因为我认为使用独特的更有意义)
由于效率是一个目标,我们应该对这些进行基准测试.
# Let's create some sample data xx <- lapply(rep(100,15),sample) ll <- as.list(sample(xx,1000,T)) ll
把它反对一些becnhmarks
fun1 <- function(ll) { ll[c(TRUE,!sapply(2:length(ll),function(i) ll[i] %in% ll[1:(i-1)]))] } fun2 <- function(ll) { ll[!duplicated(sapply(ll,digest))] } fun3 <- function(ll) { ll[!duplicated(ll)] } fun4 <- function(ll) { unique(ll) } #Make sure all the same all(identical(fun1(ll),fun2(ll)),identical(fun2(ll),fun3(ll)),identical(fun3(ll),fun4(ll)),identical(fun4(ll),fun1(ll))) # [1] TRUE library(rbenchmark) benchmark(digest=fun2(ll),duplicated=fun3(ll),unique=fun4(ll),replications=100,order="relative")[,c(1,3:6)] test elapsed relative user.self sys.self 3 unique 0.048 1.000 0.049 0.000 2 duplicated 0.050 1.042 0.050 0.000 1 digest 8.427 175.563 8.415 0.038 # I took out fun1,since when ll is large,it ran extremely slow
最快选项:
unique(ll)