2013-05-18 12 views
41

Pracowałem nad kilkoma projektami, które wymagały ode mnie wykonania wielu podzbiorów list i podczas profilowania kodu zdałem sobie sprawę, że obiekt [["nameHere"]] podejście do list podzbiorów był zwykle szybszy niż obiekt $ nazwaHere podejście.

Jako przykład jeśli tworzymy listę z wymienionych składników:

system.time (
for (i in 1:10000) { 
    a.long.list[["something997"]] 
} 
) 


user system elapsed 
0.15 0.00 0.16 

szybciej niż to::

a.long.list <- as.list(rep(1:1000)) 
names(a.long.list) <- paste0("something",1:1000) 

Dlaczego to

system.time (
    for (i in 1:10000) { 
     a.long.list$something997 
    } 
) 

user system elapsed 
0.23 0.00 0.23 

Moje pytanie jest po prostu czy to zachowanie jest prawdziwe powszechnie i powinienem unikać podzbioru $ tam, gdzie to możliwe lub robi najbardziej wydajne c Hoice zależy od kilku innych czynników?

+9

+1. Podejrzewam, że jest to związane z częściowym dopasowaniem ze znakiem '$'. Załóżmy, że masz 'my_list <- list (" a "= 1," as "= 2)'. Jeśli wypróbujesz 'my_list $ ac', otrzymasz' as ", ale jeśli spróbujesz' my_list [["ac"]] ', to nic nie znajdzie. – Frank

+1

Nie odpowiadając na twoje pytanie, ale jeśli wydajność była problemem, wolałbyś napisać wektoryzowane look-up 'query <- sample (names (a.long.list), 1000); a.long.list [query] 'aby dobrze grać z innym wektoryzowanym kodem. –

+5

Nie wykluczam teorii częściowego dopasowywania, ale mam nadzieję, że pełna odpowiedź będzie zawierała to, dlaczego dodanie 'exact = FALSE' do' [['w przykładzie OP nie pogarsza wydajności. – flodel

Odpowiedz

9

Funkcja [[ najpierw przechodzi wszystkie elementy próbujące dokładnego dopasowania, następnie próbuje wykonać częściowe dopasowanie. Funkcja $ próbuje zarówno dokładnego, jak i częściowego dopasowania każdego elementu po kolei. Jeśli wykonasz:

system.time (
    for (i in 1:10000) { 
    a.long.list[["something9973", exact=FALSE]] 
    } 
) 

tj używasz częściowe dopasowanie gdzie nie ma dokładnego odpowiednika, można zauważyć, że $ jest w rzeczywistości bardzo nieznacznie szybciej.

+0

Myślę, że to odpowiada na pytanie wyjaśniające Flodel o tym, dlaczego dodanie = FALSE nie pogarsza wydajności.W każdym razie jestem teraz przekonany, że w kontekstach programistycznych, w których liczy się prędkość, lepiej będzie użyć [[chyba że istnieje duże prawdopodobieństwo konieczności częściowego dopasowania (co częściej powoduje błędy w moich programach niż rozwiązuje problemy). –

Powiązane problemy