2
\$\begingroup\$

Is there a way to speed-up the following R code?

actionVec<-NULL
for(iii in 1:length(resultTable$V1)){
actionVec[iii]<- sum(browse$V2==resultTable$V1[iii] & browse$V4 == i & browse$V5 == ii)}

this is a loop to form a vector for each record (row) in resultTable, containing the number of entries that match the conditions in table browse

this script runs 36 minutes. I suspect that there is a way to make it run much faster. I have experienced a reduction from 15 min to 10 ms (!) on another script when avoiding loops but using vectors. But in this case I can`t find out how to make it.

EDIT1: variables i and ii come from outer loop and may be two arbitrary integers for this loop.

EDIT2: more complete version

SESSION_NUMBER<-length(resultTable$V1)

for(i in 1:55){ for(ii in 1:21){  
if(sum(browse$V4 == i & browse$V5 == ii) > treshold){
actionVec<-NULL
for(iii in 1:SESSION_NUMBER){
actionVec[iii]<- sum(browse$V2==resultTable$V1[iii] & browse$V4 == i & browse$V5 == ii)}
resultTable[,i+1] <- actionVec
}}} 
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Yes, there is:

Since i and ii and browse$V4 and browse$V5 are outside of the loop, you can precalculate this before going into the loop. That way you can save a small bit of calculating.

if (sum(browse$V4 == i & browse$V5 == ii) > treshold)

I dunno what you're doing here, but from what I can see, you're calling sum(1) or sum(0). Naturally, this produces 0 or 1. Then you're comparing it to treshold. Well, if treshold is below 1 but not below 0, then you can just remove the check, as well as the for loop, since browse doesn't change in the for loop!

If treshold is below 0, then the check is not needed. Thus, (please check if my syntax is correct)

SESSION_NUMBER<-length(resultTable$V1)

if(treshold < 1 && treshold >= 0){
    //check if browse$V4 and browse$V5 are in range
    if(browse$V4 >= 1 && browse$V4 <= 55 && browse$V5 >= 1 && browse$V5 <= 21){
        actionVec<-NULL
        for(iii in 1:SESSION_NUMBER){
            actionVec[iii]<- sum(browse$V2==resultTable$V1[iii])
        }
        resultTable[,browse$V4+1] <- actionVec
    }
} else if (treshold < 0){
    for(i in 1:55){ 
        for(ii in 1:21){  
            actionVec<-NULL
            temp<-browse$V4 == i & browse$V5 == ii
            for(iii in 1:SESSION_NUMBER){
                actionVec[iii]<- sum(browse$V2==resultTable$V1[iii] & temp)
            }
            resultTable[,i+1] <- actionVec
        }
    } 
}
\$\endgroup\$
4
  • \$\begingroup\$ thank you! will check the improved performance but I think there still might be a way to drastically improve performance \$\endgroup\$ Commented Oct 16, 2015 at 8:59
  • \$\begingroup\$ @YavpolnomShoke Any improved performance is likely going to be on a semantic level - the current code is too short to show me what else could be changed. \$\endgroup\$
    – Pimgd
    Commented Oct 16, 2015 at 9:00
  • \$\begingroup\$ I added the wrapping loops (please see Edit2) but I think they cant be avoided so I focus on the inner one \$\endgroup\$ Commented Oct 16, 2015 at 9:04
  • \$\begingroup\$ @YavpolnomShoke I think they're really weird, please check my code and the idea, I don't know R (never used before) but your code seems weird to me, with the sums adding nothing but a single number \$\endgroup\$
    – Pimgd
    Commented Oct 16, 2015 at 9:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.