2015-12-29 33 views
6

R'de çoklu mantıksal karşılaştırma gerçekleştirmenin en hızlı yolu nedir?R'de çoklu mantıksal karşılaştırma yapmanın en hızlı yolu nedir?

vektör x

set.seed(14) 
x = sample(LETTERS[1:4], size=10, replace=TRUE) 

Ben x her girişin "A" veya "B" ya olup olmadığını test etmek istiyorum (başka değil bir şey) örneğin düşünün. Aşağıdaki kodlar, tüm vektörün uzunluğu boyunca üç kez döngüler açar. R'de sadece bir kez dönmenin bir yolu var mı ve her bir maddeyi bir ya da bir başka koşulu yerine getirip getirmediğini test edin? Böyle küçük İçin

#include <Rcpp.h> 

// [[Rcpp::export]] 
Rcpp::LogicalVector single_pass(Rcpp::CharacterVector x, Rcpp::String a, Rcpp::String b) { 
    R_xlen_t i = 0, n = x.size(); 
    Rcpp::LogicalVector result(n); 

    for (; i < n; i++) { 
    result[i] = (x[i] == a || x[i] == b); 
    } 

    return result; 
} 

: Hedefiniz tek bir geçiş yapmak için sadece ise

+3

ne hakkında: '% c,% c (" A "," B ") – MrFlick

+2

@MrFlick Bu iki seçeneği zamanlama ile oynuyordum ve gerçekten bir fark görmüyorum. Ölçek her şeyden daha büyükken bile nanosaniyedir. Bu yüzden biraz kaybettim. – joran

+3

@joran Evet, büyük bir hız artışı görmüyorsun (ve bunun nerede olduğuna şüphe duyarım) performans darboğazıdır) ama sadece bir sözdizimi alternatifi. – MrFlick

cevap

12

, yani sen C++ çok deneyimli olmasa bile, Rcpp yazmak için oldukça basittir Bu y

r_fun <- function(X) X == "A" | X == "B" 
## 
cpp_fun <- function(X) single_pass(X, "A", "B") 
## 
all.equal(r_fun(x), cpp_fun(x)) 
#[1] TRUE 
microbenchmark::microbenchmark(
    r_fun(x), cpp_fun(x), times = 1000L) 
#Unit: microseconds 
#expr   min lq  mean median  uq max neval 
#r_fun(x) 1.499 1.584 1.974156 1.6795 1.8535 37.903 1000 
#cpp_fun(x) 1.860 2.334 3.042671 2.7450 3.1140 51.870 1000 

Ama daha büyük vektörler için

(I varsayarak, sizin örnekte kullanılan birine .Call (muhtemelen) maskeleri Rcpp versiyonunun hızı hafif yükü olarak itiraz bizim gerçek niyeti), daha hızlı ölçüde geçerli: bunun için herhangi bir kullanımı var ise

x2 <- sample(LETTERS, 10E5, replace = TRUE) 
## 
all.equal(r_fun(x2), cpp_fun(x2)) 
# [1] TRUE 
microbenchmark::microbenchmark(
    r_fun(x2), cpp_fun(x2), times = 200L) 
#Unit: milliseconds 
#expr    min  lq  mean median  uq  max neval 
#r_fun(x2) 78.044518 79.344465 83.741901 80.999538 86.368627 149.5106 200 
#cpp_fun(x2) 7.104929 7.201296 7.797983 7.605039 8.184628 10.7250 200 

Burada, yukarıda genelleme bir quick attempt bu.