【问题标题】:Check whether two vectors contain the same (unordered) elements in R检查两个向量是否包含 R 中的相同(无序)元素
【发布时间】:2015-01-12 23:53:16
【问题描述】:

我想检查两个向量是否包含相同的元素,即使它们的顺序不同。例如,函数(我们称之为SameElements)应该满足以下条件:

SameElements(c(1, 2, 3), c(1, 2, 3))  # TRUE
SameElements(c(1, 2, 3), c(3, 2, 1))  # TRUE
SameElements(c(1, 2, 1), c(1, 2))  # FALSE
SameElements(c(1, 1, 2, 3), c(3, 2, 1))  # FALSE

编辑 1:指定当向量包含相同元素但频率不同时,函数应返回 F。

编辑 2:清理问题以省略初始答案,因为这现在是我的实际答案。

【问题讨论】:

  • all(a %in% b) 怎么样。它基本上回答了问题a 的所有元素都包含在向量b 中吗? 如果值是唯一的,那么您也可以使用类似anyNA(match(a,b))
  • 啊,好电话,抱歉这里不清楚。在那种情况下,我正在寻找 F(为清楚起见,问题已编辑)。

标签: r


【解决方案1】:

我觉得你可以用setequal(a,b)

更新更新 setequal 检查两个向量是否由相同的元素组成,但不检查这些元素在每个向量中是否出现相同的情况。

【讨论】:

  • setequal 对我来说是新的,看起来很整洁。 +1
  • 基本上就是%in% :)
  • 你想通了。它也应该做一些额外的事情,因为它比较慢。但就成为“更清洁的替代品”而言,它获胜。很难得到任何清洁剂。 :)
  • @RichardScriven,基本上都是match)
  • 相同的向量长度不足以满足 OP 的要求。考虑setequal(c(1, 2, 1), c(1, 2, 2)) # [1] TRUE
【解决方案2】:

代替更清洁的替代方案,这是已知的解决方案:

SameElements <- function(a, b) return(identical(sort(a), sort(b)))
SameElements(c(1, 2, 3), c(1, 3, 2))  # TRUE
SameElements(c(1, 2, 3), c(1, 1, 3, 2))  # FALSE

根据 nrussell 的建议编辑:identical 而不是 all.equal(...) == T

【讨论】:

  • 有点毛骨悚然,但F &lt;- function(a,b) identical(sort(a),sort(b)) 将为您节省 3 次击键(==T),而不是上面的 SameElements 函数 - 虽然 +1 的问题很巧妙。
【解决方案3】:

您可能对“比较”包感兴趣。此答案演示了 compare() 函数,但对于您的情况,您可能会使用 compareIgnoreOrder() (它几乎与您的问题的标题完全匹配)。

有几个参数可以添加为在尝试比较元素时应允许的转换。在下面的示例中(为了节省一些输入),我要求该函数允许所有转换 (allowAll = TRUE),但更改向量长度 (shorten = FALSE) 除外。

library(compare)
compare(A1, A2, allowAll = TRUE, shorten = FALSE)
# TRUE
compare(A1, A3, allowAll = TRUE, shorten = FALSE)
# TRUE
#   sorted
compare(A1, A4, allowAll = TRUE, shorten = FALSE)
# FALSE
#   sorted
compare(B1, B2, allowAll = TRUE, shorten = FALSE)
# FALSE
#   sorted
compare(B1, A4, allowAll = TRUE, shorten = FALSE)
# FALSE
#   sorted
compare(A3f, A1, allowAll = TRUE, shorten = FALSE)
# TRUE
#   coerced from <numeric> to <factor>
#   sorted

样本数据:

A1 <- c(1, 2, 3); A2 <- c(1, 2, 3)
A3 <- c(3, 2, 1); A4 <- c(1, 1, 2, 3)
B1 <- c(1, 2, 1); B2 <- c(1, 2)
A3f <- factor(A3)

【讨论】:

    【解决方案4】:

    这是我的解决方案:

    SameElements <- function (a,b){
      l <- Map(table,list(a, b)) # Compute frequencies - returns ordered table
      Reduce(identical,l) # Check if frequencies are the same for all input vectors
    }
    
    SameElements(c(1, 2, 3), c(1, 2, 3))  # TRUE
    SameElements(c(1, 2, 3), c(3, 2, 1))  # TRUE
    SameElements(c(1, 2, 1), c(1, 2))  # FALSE
    SameElements(c(1, 1, 2, 3), c(3, 2, 1))  # FALSE
    

    正如您所见,只要您将它们全部放在一个列表中,它就适用于任意数量的输入向量。

    一个班轮:

    Reduce(identical,Map(table,listOfVectors))
    

    【讨论】:

      【解决方案5】:

      基本上你的问题可以在这些步骤中概述:

      if not same unique values: return FALSE
      else if same Frequencies: return TRUE
          else return True
      

      在适当的 R 代码中:

      SameElements = function(v1, v2)
      {
        tab1 = table(v1) ; tab2 = table(v2)
        if( !all(names(tab1) == names(tab2)) ) return(FALSE) # Same unique values test
        return(all(tab1==tab2)) # Same frequencies test
      }
      

      一些例子:

      v1 = c(1, 2, 3)
      v2 = c(3, 2, 1)
      SameElements(v1, v2) # TRUE as both uniqueness and frequencies test are verified
      
      v1 = c(1,1, 2,3)
      v2  =c(3,2,1)
      S
      

      ameElements(v1, v2) # FALSE 因为违反了频率测试

      PS : i) 您可以将 !all() 替换为 any()
      ~~~ii) 为了加快代码速度,当两个向量不匹配时,您可以快速返回FALSE
      ~~~有相同的长度,从而避免频率计算。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-05-17
        • 2019-08-24
        • 2012-08-21
        • 2023-03-18
        • 1970-01-01
        • 2010-12-06
        • 1970-01-01
        相关资源
        最近更新 更多