Check whether two vectors contain the same (unordered) elements in R

前端 未结 5 1174
予麋鹿
予麋鹿 2021-01-01 11:24

I\'d like to check whether two vectors contain the same elements, even if they\'re not ordered the same. For example, the function (let\'s call it SameElements)

相关标签:
5条回答
  • 2021-01-01 11:34

    Basically your problem can be outlined in those steps :

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

    In proper R code :

    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
    }
    

    Some examples :

    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 as frequencies test is violated

    PS : i) You can replace !all() by any()
    ~~~ii) To speed up the code you can quickly return FALSE when the two vectors don't
    ~~~have the same length, thus avoiding frequencies computation.

    0 讨论(0)
  • 2021-01-01 11:48

    You may be interested in the "compare" package. This answer demonstrates the compare() function, but for your case, you might do just fine with compareIgnoreOrder() (which matches almost exactly with your question's title).

    There are several arguments that can be added as transformations that should be allowed in attempting to compare the elements. In the examples below (to save some typing), I've asked the function to allow all transformations (allowAll = TRUE) except for changing the vector length (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
    

    Sample data:

    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)
    
    0 讨论(0)
  • 2021-01-01 11:48

    Here is my solution:

    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
    

    As you can see it works for any number of input vectors as long as you put them all in a list.

    One liner:

    Reduce(identical,Map(table,listOfVectors))
    
    0 讨论(0)
  • 2021-01-01 11:56

    In lieu of a cleaner alternative, here's the known solution:

    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
    

    Edit: identical instead of all.equal(...) == T per nrussell's suggestion.

    0 讨论(0)
  • 2021-01-01 12:01

    I think you can use setequal(a,b)

    Updated update setequal checks if two vectors are composed of the same elements but it does not check if these elements have the same occurrences in each vector.

    0 讨论(0)
提交回复
热议问题