测试一个值在 R 中的向量中是否唯一

Test if a value is unique in a vector in R

让我们假设以下示例:

test<-c(1:5,3:7)

这给出了

test
[1] 1 2 3 4 5 3 4 5 6 7

我想要一个简单的函数,如果该值在向量中是唯一的,则 returns 为 TRUE。

[1] TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE

我试过的:

unique(test) 只返回唯一值,包括那些重复的值。 duplicated(test) 还我

[1] FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE TRUE FALSE FALSE

这显然不是所需的结果,因为函数会按顺序测试重复的观察结果,并且第一次出现不计为重复。我当然可以通过包含 fromLast = T 来反转控制序列并创建两个向量。在这两个中,我可以创建第三个来指示真正的唯一值……但这相当复杂。

table(test) 允许我计算每个值的出现次数

test
1 2 3 4 5 6 7 
1 1 2 2 2 1 1 

这让我更接近我想要的结果,但仍然不是所需的结果(一个相同长度的向量表明它在向量中是否唯一。)


所以有人知道如何更容易地做到这一点吗?

匹配运算符 %in% 很有帮助:

!test %in% test[duplicated(test)]
test<-c(1:5,3:7)
isUnique <- function(vector){
                 return(!any(duplicated(vector)))
           }
isUnique(test)

如果向量的值是唯一的

,函数将return为真

您最初的建议是将 duplicated()fromLast = TRUE 开关与 OR 运算符结合使用,这似乎是一个简单而优雅的解决方案:

test <- c(1:5, 3:7)
test
## [1] 1 2 3 4 5 3 4 5 6 7

duplicated(test) # incorrect result
## [1] FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE FALSE

duplicated(test) | duplicated(test, fromLast = TRUE) # correct result
## [1] FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE

当使用 data.table 按组执行操作时,这个游戏很好,如果您的变量名称是行值或组列向量,语法会使它变得不明确。

虽然已经有一段时间了,但另一种选择。让数字说话:

library(microbenchmark)
library(DescTools)

set.seed(1789)
x <- sample(round(rnorm(1000), 3), 1e5, replace = TRUE)
bm <- microbenchmark(
            "!AllDuplicated(x)"             = !AllDuplicated(x),
            "!x %in% x[duplicated(x)]"      = !x %in% x[duplicated(x)]
      )
print(bm , unit="relative" , digits=3 , order="median" )

Unit: relative
                     expr  min   lq mean median   uq   max neval cld
        !AllDuplicated(x) 1.00 1.00 1.00   1.00 1.00 1.000   100   a
 !x %in% x[duplicated(x)] 1.44 1.43 1.16   1.45 1.52 0.143   100   a

于是我们看到了DescTools::AllDuplicated(),顺便实现了joaoal公式化的解法思路,x为数字取胜,字符处理失败(虽然只针对中位数,不是运行的平均值)。

z <- as.character(x)
bm <- microbenchmark(
            "!AllDuplicated(z)"             = AllDuplicated(z),
            "!z %in% z[duplicated(z)]"      = !z %in% z[duplicated(z)]
       )
print(bm , unit="relative" , digits=3 , order="median")

Unit: relative
                     expr  min   lq mean median   uq  max neval cld
 !z %in% z[duplicated(z)] 1.00 1.00 1.00   1.00 1.00 1.00   100   a
        !AllDuplicated(z) 1.09 1.09 0.97   1.06 0.68 1.16   100   a