2016-03-31 34 views
0

Göreceli olarak çalıştırmam gereken temel bir görevin performansını artırmaya çalışıyorum. Bir dataframe şöyle 'test' var:Döngüyü değiştirin Veri çerçevesine uygula

 pair_id rr im db 
    1 A0A0B5JQ66_A0A0B5JFG2 NA yes NA 
    2 A0A024RA76_A0A024RA76 NA yes NA 
    3 A0A068F1B9_A0A068F1B9 NA yes NA 
    4 A0A098_A0A098 NA yes NA 
    5 A0A0B5JJY8_A0A0B5JFB4 yes NA NA 
    6 A0A0B5JK11_A0A0B5JK11 yes NA NA 
    7 A0A0B5JK74_A0A0B5JFG2 yes NA NA 
    8 A0A0B5JK74_A0A0B5JK74 yes NA NA 
    9 A0A0B5JKA2_A0A0B5JF96 NA yes NA 
    10 A0A0B5JKA2_A0A0B5JK74 NA yes NA 
    11 A0A0B5JPZ7_A0A0B5JFG2 yes yes NA 
    12 A0A0B5JPZ7_A0A0B5JK74 NA yes NA 
    13 A0A0B5JPZ7_A0A0B5JKA2 NA yes NA 
    14 A0A0B5JPZ7_A0A0B5JPZ7 NA yes NA 
    15 A0A0B5JQ10_A0A0B5JK95 yes yes NA 
    16 A0A0B5JQ14_A0A0B5JFB4 NA yes NA 
    17 A0A0B5JQ25_A0A0B5JFB4 NA yes NA 
    18 A0A0B5JQ25_A0A0B5JFB8 NA yes NA 
    19 A0A0B5JQ25_A0A0B5JK29 NA yes NA 
    20 A0A0B5JQ29_A0A0B5JQ14 yes NA NA 

Ben sütunları 2 ve 3 ('rr' ve 'im') karşılaştırmak gerekir ve daha sonra bu karşılaştırmaya dayanılarak sütun numarası 4 için bir değer ayarlayın. Sadece girdi olarak iki unsurdan bir vektör alır

compare <- function(v){ 
    if (v[1]=="yes" & is.na(v[2])){ 
    db <- "rr" 
    } 
    else if (v[2]=="yes" & is.na(v[1])){ 
    db <- "im" 
    } 
    else if (v[1]=="yes" & v[2]=="yes"){ 
    db <- "both" 
    } 
    else { 
    db <- "check" 
    } 
    db 
} 

, çekler bir "evet" bir değere sahiptir ve hangisinin boş olduğunu (varsa): Bunun için ben 'karşılaştırmak' denilen şu fonksiyonu oluşturduk ve üçüncü bir sütuna atanabilecek bir değer döndürür. Şimdi

kullanıyorum 'test' bu kullanıyoruz bir for döngüsü:

for (i in 1:nrow(test)){ 
     test[i,]$db <- compare(test[i,2:3]) 
} 

benim veri çerçeveleri büyük olmak olsun, bu çözüm (I 700000 üzerinde bazı yönetmek zorunda ancak çok verimsiz satırlar) ve hesaplamak için çok zaman alır. Fonksiyonumu 'başvuru' ailesinin farklı varyantları altında kullanmaya çalışıyorum, ancak çalışamayacağımı, çünkü R'ye yeni olduğum için ve bu işlevler kümesinde çok fazla tecrübem yok. Preformansı artıracak bir alternatif hakkında ipuçları var mı?

cevap

0

Sen isteyebilirsiniz yapmak olacaktır Bir fonksiyonu

test$db <- apply(test[, 2:3], compare) 

uygulamak kullanabilirsiniz ama bu

çok daha hızlı olmayacak bunu dene. Size bir performans artışı vermeli. bir cevap verdi herkese

library(dplyr) test <- mutate(test, db = ifelse(rr == "yes" & is.na(im), "rr", ifelse(is.na(rr) & im == "yes", "im", ifelse(rr == "yes" & im == "yes", "both", "check"))))

2

Daha hızlı bir çözüm vektorızasyon kullanımı

test$db <- "check" #make column of default values 
test$db[test$rr == "yes" & is.na(test$im)] <- "rr" 
test$db[test$im == "yes" & is.na(test$rr)] <- "im" 
test$db[test$rr == "yes" & test$im == "yes"] <- "both" 
0

teşekkürler. Aslında 10000 satır uzunluğunda bir test veri çerçevesi kullanarak orijinal for-loop ile önerilen farklı yaklaşımları denedim ve karşılaştırdım. İşte ne var:

    user system elapsed 
    ptm_loop  4.831 0.551 5.390 
    ptm_apply  0.055 0.002 0.056 
    ptm_vect  0.046 0.001 0.046 
    ptm_dplyr  0.009 0.000 0.009 

PTM tabii işlem süresi için kısa ve önerilen çözümlerin her biri açıklayıcı kısaltması ile listelenir. Hepsi performansa önemli bir artış sağlar, ancak şu ana kadarki en hızlı çözüm Psidom'un yaptığı dplyr-tabanlı öneridir.