2015-06-15 23 views
21

Giả sử rằng tôi có năm vectơ:Sử dụng giống hệt nhau() trong R với nhiều vectơ

A<-1:10 
B<-1:10 
C<-1:10 
D<-1:10 
E<-1:12 

tôi có thể kiểm tra hai tại một thời gian sử dụng giống hệt nhau().

identical(A,C) 

Nhưng tôi muốn kiểm tra TẤT CẢ chúng cùng một lúc để xem BẤT K of NÀO khác với những người khác. Có cách nào làm dễ hơn không?

Trả lời

16

tôi sẽ chỉ chọn một, nói A, và làm tất cả những so sánh cặp-khôn ngoan với nó.

all(sapply(list(B, C, D, E), FUN = identical, A)) 
# [1] FALSE 

Tháo all() để xem người ta không giống hệt nhau (s)

sapply(list(B, C, D, E), FUN = identical, A) 
# [1] TRUE TRUE TRUE FALSE 

identical nên được bắc cầu, vì vậy nếu A giống hệt CD, sau đó C nên giống với D .

(Nhờ @docendo discimus cho cú pháp đơn giản.)

+2

Một cải tiến nhỏ sẽ là sử dụng hàm all() trước mặt sapply() để nó trả về một true/false. – Andy

10

Suy nghĩ đầu tiên là làm unique trên danh sách các vectơ và kiểm tra độ dài. Nếu có hai hoặc nhiều vectơ đó là khác nhau, sau đó chiều dài của danh sách kết quả sẽ lớn hơn 1.

length(unique(list(A,B,C,D))) == 1 
[1] TRUE 

length(unique(list(A,B,C,D,E))) == 1 
[1] FALSE 
+0

Tôi khá thích sự sang trọng của câu trả lời này, nhưng Tôi sẽ đánh dấu @ Gregor là tốt nhất. – Andy

+1

@Andy, nó là câu trả lời tốt hơn cho rằng nó vẫn sử dụng 'giống hệt nhau '. Tôi nên suy nghĩ về các so sánh transitive: P – cdeterman

9

Một lựa chọn khác, chỉ để cho vui:

Vectorize(identical, 'x')(list(A, B, C, D, E), C) 
2

này là khá rõ ràng, nhưng: nếu có rất nhiều yếu tố và tốt cơ hội thất bại, bạn sẽ muốn có thể ngắn mạch so sánh. Dưới đây là một vòng lặp cho rằng, với một ví dụ:

A = sample(1e3) 
Alist <- replicate(1e6,A,simplify=FALSE) 
Alist[[2]][1e3] <- 0 

system.time({brkres <- { 
    ok=TRUE 
    for (i in seq_along(Alist)) if(!identical(Alist[[1]],Alist[[i]])){ 
    ok=FALSE 
    break 
    } 
    ok 
}}) 
# user system elapsed 
#  0  0  0 

system.time({allres <- all(sapply(Alist[-1], FUN = identical, Alist[[1]]))}) 
# user system elapsed 
# 1.66 0.03 1.68 

Nếu bạn bỏ qua dòng Alist[[2]][1e3] <- 0, vì vậy mà tất cả chúng đều giống hệt nhau, họ dành thời gian tương tự.

-1

Tôi đã gặp vấn đề tương tự nhưng đã quyết định triển khai giải pháp dựa trên Reduce và một dựa trên vòng lặp for đôi.

Chức năng:

all_elements_the_same = function(list) { 

    #func to compare with 
    comparison_func = function(x, y) { 
    if (!identical(x, y)) stop() #stop function if it finds a non-identical pair 
    y #return second element 
    } 

    #run comparisons 
    trial = try({ 
    Reduce(f = comparison_func, x = list, init = list[[1]]) 
    }, silent = T) 

    #return 
    if (class(trial) == "try-error") return(F) 
    T 
} 

all_elements_the_same2 = function(list, ignore_names = F) { 
    #double loop solution 
    for (i in seq_along(list)) { 
    for (j in seq_along(list)) { 
     #skip if comparing to self or if comparison already done 
     if (i >= j) next 

     #check 
     if (!identical(list[[i]], list[[j]])) return(F) 
    } 
    } 
    T 
} 

đối tượng kiểm tra: chức năng

l_testlist_ok = list(1:3, 1:3, 1:3, 1:3, 1:3, 1:3) 
l_testlist_bad = list(1:3, 1:3, 1:4, 1:3, 1:3, 1:3) 
l_testlist_bad2 = list(1:3, 1:3, 1:4, 1:3, 1:3, 1:3, 1:3, 1:3, 1:3, 1:3, 1:3, 1:3, 1:3, 1:3, 1:3) 

Test:

> all_elements_the_same(l_testlist_ok) 
[1] TRUE 
> all_elements_the_same(l_testlist_bad) 
[1] FALSE 
> all_elements_the_same(l_testlist_bad2) 
[1] FALSE 
> all_elements_the_same2(l_testlist_ok) 
[1] TRUE 
> all_elements_the_same2(l_testlist_bad) 
[1] FALSE 
> all_elements_the_same2(l_testlist_bad2) 
[1] FALSE 

Kiểm tra thời gian sử dụng:

> library(microbenchmark) 
> microbenchmark(all_elements_the_same(l_testlist_ok), 
+ all_elements_the_same(l_testlist_bad), 
+ all_elements_the_same(l_testlist_bad2), 
+ all_elements_the_same2(l_testlist_ok), 
+ all_elements_the_same2(l_testlist_bad), 
+ all_elements_the_same2(l_testlist_bad2), times = 1e4) 
Unit: microseconds 
            expr min  lq  mean median  uq  max neval 
    all_elements_the_same(l_testlist_ok) 19.310 25.454 28.309016 26.917 28.380 1003.228 10000 
    all_elements_the_same(l_testlist_bad) 93.624 100.938 108.890823 103.863 106.497 3130.807 10000 
    all_elements_the_same(l_testlist_bad2) 93.331 100.938 107.963741 103.863 106.497 1181.404 10000 
    all_elements_the_same2(l_testlist_ok) 48.275 53.541 57.334095 55.881 57.930 926.866 10000 
    all_elements_the_same2(l_testlist_bad) 6.144 7.315 8.437603 7.900 8.778 998.839 10000 
all_elements_the_same2(l_testlist_bad2) 6.144 7.315 8.564780 8.192 8.778 1323.594 10000 

Vì vậy, rõ ràng, phần try làm chậm nó xuống đáng kể. Nó vẫn có thể tiết kiệm thời gian để sử dụng các biến thể Reduce nếu một trong những có đối tượng rất lớn, nhưng đối với các đối tượng nhỏ hơn, đôi vòng lặp for dường như là con đường để đi.

0

Giải pháp nhanh nhất và đơn giản sử dụng Rcpp:

#include <Rcpp.h> 
using namespace Rcpp; 

inline bool same(SEXP a, SEXP b) { 
    return R_compute_identical(a, b, 0); 
} 

// [[Rcpp::export]] 
bool identical_impl(List x) { 
    std::size_t n = x.size(); 
    for (std::size_t i = 1; i < n; ++i) 
     if (!same(x[0], x[i])) return false; 
    return true; 
} 

/*** R 
identical2 <- function(...) { 
    identical_impl(list(...)) 
} 
*/ 

Một số tiêu chuẩn với các giải pháp khác:

A <- 1:10 
B <- 1:10 
C <- 1:10 
D <- 1:10 
E <- 1:12 
identical2 <- function(...) { 
    identical_impl(list(...)) 
} 
identical3 <- function(...) { 
    length(unique(list(...))) == 1L 
} 
identical4 <- function(...) { 
    l <- list(...) 
    all(vapply(l[-1], l[[1]], FUN = identical, 
       FUN.VALUE = logical(1L), USE.NAMES = FALSE)) 
} 
identical5 <- function(...) { 
    l <- list(...) 
    Vectorize(identical, 'x')(l[-1], l[[1L]]) 
} 
identical6 <- function(...) { 
    l <- list(...) 
    for (i in seq_along(l)) { 
     if (!identical(l[[1]], l[[i]])) return(FALSE) 
    } 
    return(TRUE) 
} 
identical7 <- function(...) { 
    l <- list(...) 
    for (i in seq_along(l)) { 
     for (j in seq_along(l)) { 
      if (i >= j) next 
      if (!identical(l[[1]], l[[i]])) return(FALSE) 
     } 
    } 
    return(TRUE) 
} 
library(microbenchmark) 
microbenchmark(
    identical2(A, B, C, D, E), 
    identical3(A, B, C, D, E), 
    identical4(A, B, C, D, E), 
    identical5(A, B, C, D, E), 
    identical6(A, B, C, D, E), 
    identical7(A, B, C, D, E)) 

Kết quả:

Unit: microseconds 
        expr min  lq  mean median  uq  max neval cld 
identical2(A, B, C, D, E) 3.401 4.3065 5.32136 5.1245 5.5420 21.529 100 a  
identical3(A, B, C, D, E) 6.480 7.8675 9.20970 8.3875 9.0175 26.739 100 b 
identical4(A, B, C, D, E) 12.233 13.5680 15.48014 14.7755 15.5455 48.333 100 c 
identical5(A, B, C, D, E) 90.177 93.1480 98.79570 95.2685 103.2765 178.657 100  e 
identical6(A, B, C, D, E) 10.683 12.0650 13.43184 12.6820 13.4060 22.314 100 c 
identical7(A, B, C, D, E) 28.202 31.0800 34.97819 32.4630 39.4960 68.902 100 d 
Các vấn đề liên quan