2014-02-20 1 views
0

문자 배열을 기반으로 다른 함수 (fn1)를 호출하는 아래 함수 (fndf)의 속도를 높이고 싶습니다.성능 향상을 위해`for` 루프 대신`apply/lapply/sapply`를 어떻게 사용할 수 있습니까?

fndf - 새로운 함수
list_s - 문자 배열 - chr [1:400]
rdata_i - 빈 데이터 프레임 (초기화)
fn1 - 다른 커스텀 기능
rdata2-3000 obs of 40 variables
mdata와 데이터 프레임 - data.frame
nm - 문자

fndf = function(list_s, rdata2){ 
       rdata_i = df <- data.frame(Date=as.Date(character()), 
         File=character(), 
         User=character(), 
         stringsAsFactors=FALSE) 
       for(i in 1:length(list_s)) 
       { 
        rdata = fn1(list_s[i], rdata2) 
        rdata_i = rbind(rdata, rdata_i) 
       } 
       return(unique(rdata_i)) 
      } 

function의 성능을 향상시킬 수 있습니까?

fn1 = function(nm, mdata){ 
       n0 = mdata[mdata$Sign==nm,] 
       cn0 = unique(c(n0$Name)) 
       repeat{ 
         n1c = mdata[mdata$Mgr %in% cn0,] 
         n0 = unique(rbind(n0,n1c)) 
         if(nrow(n1c)==0){ 
           return(n0) 
           break 
           } 
         cn0= unique(c(n1c$Name)) 
         } 
       } 
+2

당신의 둔화는 아마도'rdata_i = rbind (rdata, rdata_i)'때문일 것입니다; 일반적으로 for 루프에서 객체를 성장시키는 것은 나쁜 습관입니다 (너무 많은 복사 및 데이터 이동). "R Inferno"책을 확인해보십시오.이 책에 대한 조언이 있습니다. – baptiste

+2

이것을 시도해 보면,'ld = lapply (list_s, fn1, rdata2); do.call (rbind, ld)' – baptiste

+0

질문을 재현 가능하게 만들어야합니다. 아마도 루프가 필요하지 않을 수도 있습니다. – Roland

답변

3

성명을 발표하고, 이것이 더 빨리 할 것인지 말하기가 더 어렵습니다. 하지만 근본적으로 다음과 같은 변형이 여러분이 겪은 것이며, 함수를 더 간단하고 읽기 쉽게 만듭니다. 티스트에 의해 언급 된 바와 같이 또한 아마도 인해 반복 rbind의 손실에 상당한 성능 향상에 해당

fndf = function (list_s, rdata2) 
    as.data.frame(do.call(rbind, unique(lapply(list_s, fn1, rdata2)))) 

(.. 예 즉, 하나의 문입니다)

또한 난 있습니다 이제 data.frame이 아닌 unique을 목록에 직접 적용하십시오. 이것은 이 data.frame에 특화된 의미를 변경하지만, 아마도 당신의 목적에 옳은 것이며 불필요하게 커다란 행을 가진 data.frame을 만들지 않는다는 것을 의미하기 때문에 더 효율적일 것입니다.

+0

이것은 15 초로 단축되었습니다. 감사. – BigDataScientist

1

그것은 당신의 데이터/기능없이 말할 어렵지만, 여기 plyr와 솔루션 및 일부 자리 데이터 : 그것은 가장 잘 *apply로 루프를 변환하는 방법을 말하기 어렵 참이다

list_s<-LETTERS 
rdata2<-data.frame(a=rep(LETTERS,2),b=runif(52),c=runif(52)*10) 
fn1<-function(a,b=rdata2)b[rdata2$a==a,] 
fn1("A") 

require(plyr) # for ldply function, which takes a list and returns a dataframe 
result<-ldply(1:length(list_s),function(x)fn1(list_s[x],rdata2)) 
head(result) 

    a   b   c 
1 A 0.281940237 2.7774933 
2 A 0.023611392 0.6067029 
3 B 0.456547803 9.4219258 
4 B 0.645783746 5.3094864 
5 C 0.475949523 4.8580622 
6 C 0.006063407 2.5851738 
관련 문제