check whether all elements of a list are in equal in R

前端 未结 5 590
挽巷
挽巷 2021-01-02 09:34

I have a list of several vectors. I would like to check whether all vectors in the list are equal. There\'s identical which only works for pairwise comparison.

相关标签:
5条回答
  • 2021-01-02 10:18

    To summarize the solutions. Data for the tests:

    x1 <- as.list(as.data.frame(replicate(1000, 1:100)))
    x2 <- as.list(as.data.frame(replicate(1000, sample(1:100, 100))))
    

    Solutions:

    comp_list1 <- function(x) length(unique.default(x)) == 1L
    comp_list2 <- function(x) all(vapply(x[-1], identical, logical(1L), x = x[[1]]))
    comp_list3 <- function(x) all(vapply(x[-1], function(x2) all(x[[1]] == x2), logical(1L)))
    comp_list4 <- function(x) sum(duplicated.default(x)) == length(x) - 1L
    

    Test on the data:

    for (i in 1:4) cat(match.fun(paste0("comp_list", i))(x1), " ")
    #> TRUE  TRUE  TRUE  TRUE   
    for (i in 1:4) cat(match.fun(paste0("comp_list", i))(x2), " ")
    #> FALSE  FALSE  FALSE  FALSE  
    

    Benchmarks:

    library(microbenchmark)
    microbenchmark(comp_list1(x1), comp_list2(x1), comp_list3(x1), comp_list4(x1))
    #> Unit: microseconds
    #>            expr      min        lq      mean   median        uq      max neval cld
    #>  comp_list1(x1)  138.327  148.5955  171.9481  162.013  188.9315  269.342   100 a  
    #>  comp_list2(x1) 1023.932 1125.2210 1387.6268 1255.985 1403.1885 3458.597   100  b 
    #>  comp_list3(x1) 1130.275 1275.9940 1511.7916 1378.789 1550.8240 3254.292   100   c
    #>  comp_list4(x1)  138.075  144.8635  169.7833  159.954  185.1515  298.282   100 a  
    microbenchmark(comp_list1(x2), comp_list2(x2), comp_list3(x2), comp_list4(x2))
    #> Unit: microseconds
    #>            expr     min        lq      mean   median        uq      max neval cld
    #>  comp_list1(x2) 139.492  140.3540  147.7695  145.380  149.6495  218.800   100  a 
    #>  comp_list2(x2) 995.373 1030.4325 1179.2274 1054.711 1136.5050 3763.506   100   b
    #>  comp_list3(x2) 977.805 1029.7310 1134.3650 1049.684 1086.0730 2846.592   100   b
    #>  comp_list4(x2) 135.516  136.4685  150.7185  139.030  146.7170  345.985   100  a
    

    As we see the most efficient solutions based on the duplicated and unique functions.

    0 讨论(0)
  • 2021-01-02 10:22

    PUtting in my self-promoting suggestion for cgwtools::approxeq which essentially does what all.equal does but returns a vector of logical values indicating equality or not.

    So: depends whether you want exact equality or floating-point-representational equality.

    0 讨论(0)
  • 2021-01-02 10:27

    How about

    allSame <- function(x) length(unique(x)) == 1
    
    allSame(test_true)
    # [1] TRUE
    allSame(test_false)
    # [1] FALSE
    

    As @JoshuaUlrich pointed out below, unique may be slow on lists. Also, identical and unique may use different criteria. Reduce is a function I recently learned about for extending pairwise operations:

    identicalValue <- function(x,y) if (identical(x,y)) x else FALSE
    Reduce(identicalValue,test_true)
    # [1] 1 2 3
    Reduce(identicalValue,test_false)
    # [1] FALSE
    

    This inefficiently continues making comparisons after finding one non-match. My crude solution to that would be to write else break instead of else FALSE, throwing an error.

    0 讨论(0)
  • 2021-01-02 10:35

    I woud do:

    all.identical <- function(l) all(mapply(identical, head(l, 1), tail(l, -1)))
    
    all.identical(test_true)
    # [1] TRUE
    all.identical(test_false)
    # [1] FALSE
    
    0 讨论(0)
  • 2021-01-02 10:37

    this also works

    m <- combn(length(test_true),2)
    
    for(i in 1:ncol(m)){
        print(all(test_true[[m[,i][1]]] == test_true[[m[,i][2]]]))
        }
    
    0 讨论(0)
提交回复
热议问题