首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >移除R中所有重复项的最快方法

移除R中所有重复项的最快方法
EN

Stack Overflow用户
提问于 2016-05-10 20:40:32
回答 3查看 4.3K关注 0票数 12

我想删除所有出现在向量中不止一次的项目。具体来说,这包括字符、数字和整数向量。目前,我使用的是向前和向后的duplicated() (使用fromLast参数)。

有没有一种计算效率更高(更快)的方法在R中执行?下面的解决方案非常简单,可以写/读,但是执行重复搜索两次似乎效率低下。也许使用额外数据结构的基于计数的方法会更好?

示例:

代码语言:javascript
复制
d <- c(1,2,3,4,1,5,6,4,2,1)
d[!(duplicated(d) | duplicated(d, fromLast=TRUE))]
#[1] 3 5 6

相关的所以发布https://stackoverflow.com/questions/12495345/find-indices-of-duplicated-rowshttps://stackoverflow.com/questions/13763216/how-can-i-remove-all-duplicates-so-that-none-are-left-in-a-data-frame-in-r

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-05-10 21:18:27

一些时间安排:

代码语言:javascript
复制
set.seed(1001)
d <- sample(1:100000, 100000, replace=T)
d <- c(d, sample(d, 20000, replace=T))  # ensure many duplicates
mb <- microbenchmark::microbenchmark(
  d[!(duplicated(d) | duplicated(d, fromLast=TRUE))],
  setdiff(d, d[duplicated(d)]),
  {tmp <- rle(sort(d)); tmp$values[tmp$lengths == 1]},
  as.integer(names(table(d)[table(d)==1])),
  d[!(duplicated.default(d) | duplicated.default(d, fromLast=TRUE))],
  d[!(d %in% d[duplicated(d)])],
  { ud = unique(d); ud[tabulate(match(d, ud)) == 1L] },
  d[!(.Internal(duplicated(d, F, F, NA)) | .Internal(duplicated(d, F, T, NA)))]
)
summary(mb)[, c(1, 4)]  # in milliseconds
#                                                                                expr      mean
#1                               d[!(duplicated(d) | duplicated(d, fromLast = TRUE))]  18.34692
#2                                                       setdiff(d, d[duplicated(d)])  24.84984
#3                       {     tmp <- rle(sort(d))     tmp$values[tmp$lengths == 1] }   9.53831
#4                                         as.integer(names(table(d)[table(d) == 1])) 255.76300
#5               d[!(duplicated.default(d) | duplicated.default(d, fromLast = TRUE))]  18.35360
#6                                                      d[!(d %in% d[duplicated(d)])]  24.01009
#7                        {     ud = unique(d)     ud[tabulate(match(d, ud)) == 1L] }  32.10166
#8 d[!(.Internal(duplicated(d, F, F, NA)) | .Internal(duplicated(d,      F, T, NA)))]  18.33475

考虑到这些评论,让我们看看它们是否都是正确的?

代码语言:javascript
复制
 results <- list(d[!(duplicated(d) | duplicated(d, fromLast=TRUE))],
         setdiff(d, d[duplicated(d)]),
         {tmp <- rle(sort(d)); tmp$values[tmp$lengths == 1]},
         as.integer(names(table(d)[table(d)==1])),
         d[!(duplicated.default(d) | duplicated.default(d, fromLast=TRUE))],
         d[!(d %in% d[duplicated(d)])],
         { ud = unique(d); ud[tabulate(match(d, ud)) == 1L] },
         d[!(.Internal(duplicated(d, F, F, NA)) | .Internal(duplicated(d, F, T, NA)))])
 all(sapply(ls, all.equal, c(3, 5, 6)))
 # TRUE
票数 12
EN

Stack Overflow用户

发布于 2016-05-10 21:12:15

您可以使用rle函数来完成这一任务:

代码语言:javascript
复制
tmp <- rle(sort(d))
res <- tmp$values[tmp$lengths == 1]

其思想是在向量中找到相同值的计数。

这里有很多选择:用向量中x的值计算元素数

编辑

在查看了基准之后,@ got趋势,我开始怀疑了。理论上,与原始的duplicated逻辑相比,使用一次通过的计数项必须快2倍。

我试着用data.table做这件事

代码语言:javascript
复制
library(data.table)
dt <- data.table(d)
res <-  dt[, count:= .N, by = d][count == 1]$d

以下是针对三种解决方案的不同样本大小的基准(我已经将其简化为快速、独特的方法):

您可以看到,随着样本的增长,data.table开始优于其他方法(2x)。

下面是要复制的代码:

代码语言:javascript
复制
set.seed(1001)
N <- c(3, 4, 5, 6 ,7)
n <- 10^N
res <- lapply(n, function(x) {
d <- sample(1:x/10, 5 * x, replace=T)
d <- c(d, sample(d, x, replace=T))  # ensure many duplicates
dt <- data.table(d)
mb <- microbenchmark::microbenchmark(
  "duplicated(original)" = d[!(duplicated(d) | duplicated(d, fromLast=TRUE))],
  "tabulate" = { ud = unique(d); ud[tabulate(match(d, ud)) == 1L] },
  "data.table" = dt[, count:= .N, by = d][count == 1]$d,
  times = 1,unit = "ms")
sm <- summary(mb)[, c(1, 4, 8)]
sm$size = x
return(sm)

})

res <- do.call("rbind", res)

require(ggplot2)
##The values Year, Value, School_ID are
##inherited by the geoms
ggplot(res, aes(x = res$size, y = res$mean, colour=res$exp)) + 
geom_line() + scale_x_log10() + scale_y_log10() +
geom_point() 
票数 7
EN

Stack Overflow用户

发布于 2016-05-10 21:10:18

你可以用设定操作

代码语言:javascript
复制
d <- c(1,2,3,4,1,5,6,4,2,1)
duplicates = d[duplicated(d)]
setdiff(d, duplicates)
[1] 3 5 6

(不确定这是否比上面的代码更有效,但在概念上似乎更清晰)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37148567

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档