【问题标题】:Is there an efficient way to check whether an R character vector contains the same elements?有没有一种有效的方法来检查 R 字符向量是否包含相同的元素?
【发布时间】:2018-05-04 15:53:07
【问题描述】:

假设我有一个 character 类型的 R 向量:

vector1 = c("dog", "cat", "fish")
vector2 = c("fish", "fish", "fish")

第一个向量vector1 包含三个不同的元素:狗、猫、鱼

但是,vector2 包含所有相同的元素。

我正在寻找一种有效的方法来检查 R 向量中的此属性,最好使用基本 R。

我的想法是使用以下内容:

检查length(unique(vector1))==1。如果TRUE,那么只有 1 个元素。如果FALSE,有很多。

【问题讨论】:

  • 您给出的解决方案的长度和唯一性有什么问题?
  • 您在问题中提供了一个解决方案,但您没有解释该解决方案如何或为什么对您来说不够“有效”。
  • @G5W 你是对的。这可能是基础 R 中最有效的方法。我建议删除此问题
  • @ShanZhengYang 实际上length(unique()) == 1all() 相比效率很低
  • 如果你的向量很大,uniqueN 或 anyDuplicated from package data.table 可能会感兴趣。

标签: r vector


【解决方案1】:

如果您关心速度,看起来@AshOfFire 的all(vec == vec[1])uniqueN(vec) == 1 是最好的。 all(...) 在元素不同时性能更好,但在元素相同时性能更差。这里还有关于这个主题的其他帖子:Test for equality among all elements of a single vector

由于您明确询问速度,我不知道这是否应该被标记为欺骗。做一些快速的微基准测试,您可以看到相对速度:

library(data.table)
benchmark_vec <- function(vec){
  microbenchmark::microbenchmark(length(unique(vec)) == 1,
                                 all(vec == vec[1]),
                                 isTRUE(max(vec) == min(vec)),
                                 uniqueN(vec)==1,
                                 unit = "relative")
}

看起来您最好的选择可能是使用uniqueN(vec) == 1,因为当元素不同时isTRUE(max(vec) == min(vec)) 会很慢。

相同元素的向量:

benchmark_vec(rep("a", 1e4))
#Unit: relative
#                         expr      min       lq     mean   median        uq      max neval
#     length(unique(vec)) == 1 6.059888 8.980080 8.807812 9.057240 10.131907 6.538035   100
#           all(vec == vec[1]) 2.039980 2.117614 2.517966 2.769089  2.820726 2.147200   100
# isTRUE(max(vec) == min(vec)) 1.000000 1.000000 1.000000 1.000000  1.000000 1.000000   100
#            uniqueN(vec) == 1 1.679993 1.794075 2.148665 2.442206  2.547134 1.385782   100

benchmark_vec(rep("a", 1e5))
#Unit: relative
#                         expr      min       lq     mean   median       uq       max neval
#     length(unique(vec)) == 1 5.732161 6.898531 7.935981 7.098417 6.776363 52.733981   100
#           all(vec == vec[1]) 2.084232 2.416316 2.366826 2.482896 2.454888  2.025258   100
# isTRUE(max(vec) == min(vec)) 1.000000 1.000000 1.000000 1.000000 1.000000  1.000000   100
#            uniqueN(vec) == 1 1.254857 1.653767 1.632287 1.707769 1.755275  1.401932   100

benchmark_vec(rep("a", 1e6))
#Unit: relative
#                         expr      min       lq     mean   median       uq      max neval
#     length(unique(vec)) == 1 5.993300 6.057139 6.478008 6.083278 6.104486 9.124542   100
#           all(vec == vec[1]) 2.249211 2.182959 2.261631 2.182345 2.224141 6.421657   100
# isTRUE(max(vec) == min(vec)) 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000   100
#            uniqueN(vec) == 1 1.325453 1.451214 1.869176 1.457588 1.470810 6.657961   100

不同元素的向量:

benchmark_vec(sample(LETTERS, 1e4, replace = TRUE))
#Unit: relative
#                         expr       min        lq      mean    median        uq  #     max neval
#     length(unique(vec)) == 1  2.989151  2.999928  3.233178  3.031249  3.260122  4.471498   100
#           all(vec == vec[1])  1.000000  1.000000  1.000000  1.000000  1.000000  1.000000   100
# isTRUE(max(vec) == min(vec)) 92.619106 91.765377 89.899963 92.227913 93.951104 64.507502   100
#            uniqueN(vec) == 1  1.478271  1.494703  1.608562  1.531235  1.637707  2.528502   100

benchmark_vec(sample(LETTERS, 1e5, replace = TRUE))
#Unit: relative
#                         expr       min        lq      mean    median        uq       max neval
#     length(unique(vec)) == 1  3.142858  3.010220  2.945582  2.887597  2.925129  4.482119   100
#           all(vec == vec[1])  1.000000  1.000000  1.000000  1.000000  1.000000  1.000000   100
# isTRUE(max(vec) == min(vec)) 97.273487 79.818135 73.850769 75.442748 71.441439 41.772795   100
#            uniqueN(vec) == 1  1.280180  1.431999  2.009661  1.431815  1.447287 32.446761   100

benchmark_vec(sample(LETTERS, 1e6, replace = TRUE))
#Unit: relative
#                         expr       min        lq      mean    median        uq       max neval
#     length(unique(vec)) == 1  3.228670  2.898367  2.799075  2.941651  2.914313  1.360938   100
#           all(vec == vec[1])  1.000000  1.000000  1.000000  1.000000  1.000000  1.000000   100
# isTRUE(max(vec) == min(vec)) 92.506220 79.923456 67.347683 78.362151 75.028194 13.611664   100
#            uniqueN(vec) == 1  2.263843  2.031869  1.861165  2.058220  2.051759  1.129074   100

【讨论】:

  • isTRUE(max(x)==min(x)) 真是个好主意……而且似乎也适用于字符向量
  • 实际上@AshOfFire 有all(vec == vec[1]) 而不是all(vec[-1] == vec[1])。无论如何,似乎进一步的测试表明试图击败data.table 是徒劳的。
  • @snoram aaannnddd 我错了!看起来 AshOfFire 是我机器上不同元素速度最快的
  • 谢谢迈克!这是一个很好的答案,因为它有基准。但是,由于@AshOfFire 确实提供了方法并且可以使用更多的声望点,我会给他/她答案。
【解决方案2】:

或者,您可以使用all

> all(vector1 == vector1[1])
[1] FALSE
> all(vector2 == vector2[1])
[1] TRUE

【讨论】:

  • 实际上,我使用microbenchmark 的解决方案获得了更快的结果:a &lt;- rep("fish",5000000); b &lt;- c(a[1:4999999], "cat"); microbenchmark(all(a == a[1]), all(a[-1] == a[1]), all(b == b[1]), all(b[-1] == b[1]))
  • @snoram 在大多数情况下,这会降低效率(我的意思是,更慢)
  • 有趣!我的错!
【解决方案3】:

受到 AshofFire 和 Mike 的启发:

!any(vec < vec[1])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 2017-10-27
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    • 2021-10-06
    相关资源
    最近更新 更多