Brigid Mooney
2008-Dec-22 20:20 UTC
[R] How can I avoid nested 'for' loops or quicken the process?
Hi All, I'm still pretty new to using R - and I was hoping I might be able to get some advice as to how to use 'apply' or a similar function instead of using nested for loops. Right now I have a script which uses nested for loops similar to this: i <- 1 for(a in Alpha) { for (b in Beta) { for (c in Gamma) { for (d in Delta) { for (e in Epsilon) { Output[i] <- MyFunction(X, Y, a, b, c, d, e) i <- i+1 }}}}} Where Output[i] is a data frame, X and Y are data frames, and Alpha, Beta, Gamma, Delta, and Epsilon are all lists, some of which are numeric, some logical (TRUE/FALSE). Any advice on how to implement some sort of solution that might be quicker than these nested 'for' loops would be greatly appreciated. Thanks! [[alternative HTML version deleted]]
Charles C. Berry
2008-Dec-22 20:33 UTC
[R] How can I avoid nested 'for' loops or quicken the process?
On Mon, 22 Dec 2008, Brigid Mooney wrote:> Hi All, > > I'm still pretty new to using R - and I was hoping I might be able to get > some advice as to how to use 'apply' or a similar function instead of using > nested for loops.Unfortunately, you have given nothing that is reproducible. The details of MyFunction and the exact structure of the list objects are crucial. Check out the _Posting Guide_ for hints on how to formulate a question that will elecit an answer that helps you. HTH, Chuck> > Right now I have a script which uses nested for loops similar to this: > > i <- 1 > for(a in Alpha) { for (b in Beta) { for (c in Gamma) { for (d in Delta) { > for (e in Epsilon) > { > Output[i] <- MyFunction(X, Y, a, b, c, d, e) > i <- i+1 > }}}}} > > > Where Output[i] is a data frame, X and Y are data frames, and Alpha, Beta, > Gamma, Delta, and Epsilon are all lists, some of which are numeric, some > logical (TRUE/FALSE). > > Any advice on how to implement some sort of solution that might be quicker > than these nested 'for' loops would be greatly appreciated. > > Thanks! > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >Charles C. Berry (858) 534-2098 Dept of Family/Preventive Medicine E mailto:cberry at tajo.ucsd.edu UC San Diego http://famprevmed.ucsd.edu/faculty/cberry/ La Jolla, San Diego 92093-0901
Brigid Mooney
2008-Dec-23 14:55 UTC
[R] How can I avoid nested 'for' loops or quicken the process?
I have used some of your advice in making some changes to my function and function call before reposting. Instead of nesting many 'for' loops, I have gotten to the point where I only have one. (Also, please note, I am pasting the function calcProfit at the end of this message as it is a bit long.) This process works correctly, but still has a 'for' loop, which I thought I would be able to avoid with 'apply'. ------------------------------------------------------------------------------------------------------------------ # Sample iteration parameters (these can be vectors of arbitrary length) # Need to iterate through all possible combinations of these parameters Param <- list(long=c(.75, 1.5), short=c(-.5, -1), investment=10000, stoploss=c(-.015), comission=.0002, penny=3, volume=c(.02, .01), numU=2, accDefn=0:1 ) CombParam <- expand.grid(Param) # Create sample X and Y data frames for function call Y <- data.frame(SymbolID=10:14, OpeningPrice = c(1,3,10,20,60), ClosingPrice = c(2,2.5,11,18,61.5), YesterdayClose= c(1,3,10,20,60), MinTrVol rep(10000000, times=5)) X <- data.frame(SymbolID=10:14, weight = c(1, .5, -3, -.75, 2), CPweight=c(1.5, .25, -1.75, 2, -1), noU = c(2,3,4,2,10)) for (i in 1:length(CombParam$long)) { if(i==1) { Results <- calcProfit(CombParam[i,], X, Y) } else { Results <- rbind(Results, calcProfit(CombParam[i,], X, Y)) } } ------------------------------------------------------------------------------------------------------------------ However, when I try to replace this for loop with 'apply', I get the following result: Results2 <- apply(CombParam, 1, calcProfit, X, Y) Error in IterParam$long : $ operator is invalid for atomic vectors Any advice that anyone could provide would be much appreciated. Here is the function which I am using: ------------------------------------------------------------------------------------------------------------------ *calcProfit* <- function(IterParam, marketData, dailyForecast) { long <- IterParam$long short <- IterParam$short investment <- IterParam$investment stoploss <- IterParam$stoploss comission <- IterParam$comission penny <- IterParam$penny volume <- IterParam$volume numU <- IterParam$numU accDefn <- IterParam$accDefn compareMarket <- merge(dailyForecast, marketData, by.x="SymbolID", by.y="SymbolID") weight <- ifelse(rep(accDefn, times=length(compareMarket$weight))==1, compareMarket$weight, compareMarket$CPweight) position <- ifelse((weight<=short & compareMarket$OpeningPrice > penny & compareMarket$noU>=numU), "S", ifelse((weight>=long & compareMarket$OpeningPrice > penny & compareMarket$noU>=numU), "L", NA)) positionTF <- ifelse(position=="L" | position=="S", TRUE, FALSE) estMaxInv <- volume*compareMarket$MinTrVol*compareMarket$YesterdayClose investbySymbol <- ifelse(positionTF==TRUE, ifelse(estMaxInv >investment, investment, 0)) opClProfit <- ifelse(position=="L", compareMarket$ClosingPrice/compareMarket$OpeningPrice-1, ifelse(position=="S", 1-compareMarket$ClosingPrice/compareMarket$OpeningPrice, 0.0)) Gains <- investbySymbol*ifelse(opClProfit <= stoploss, stoploss, opClProfit) ProfitTable <- data.frame(SymbolID=compareMarket$SymbolID, investbySymbol, Gains, percentGains=Gains/investbySymbol, LessComm=rep(comission, times=length(Gains)), NetGains=Gains/investbySymbol-2*comission) AggregatesTable <- data.frame( OutTotInvestment sum(ProfitTable$investbySymbol, na.rm=TRUE), OutNumInvestments = sum(ProfitTable$investbySymbol, na.rm=TRUE)/investment, OutDolProf = sum(ProfitTable$Gains, na.rm=TRUE), OutPerProf = sum(ProfitTable$Gains, na.rm=TRUE)/sum(ProfitTable$investbySymbol, na.rm=TRUE), OutNetGains = sum(ProfitTable$Gains, na.rm=TRUE)/sum(ProfitTable$investbySymbol, na.rm=TRUE)-2*comission, OutLong = long, OutShort = short, OutInvestment = investment, OutStoploss stoploss, OutComission = comission, OutPenny = penny, OutVolume = volume, OutNumU = numU, OutAccDefn = accDefn ) return(AggregatesTable) } ------------------------------------------------------------------------------------------------------------------ On Mon, Dec 22, 2008 at 4:32 PM, David Winsemius <dwinsemius@comcast.net>wrote:> I do agree with Dr Berry that your question failed on several grounds in > adherence to the Posting Guide, so this is off list. > > Maybe this will give you guidance that you can apply to your next question > to the list: > > > alist <- list("a","b","c") > > blist <- list("ab","ac","ad") > > > expand.grid(alist, blist) > Var1 Var2 > 1 a ab > 2 b ab > 3 c ab > 4 a ac > 5 b ac > 6 c ac > 7 a ad > 8 b ad > 9 c ad > > > apply( expand.grid(alist, blist), 1, function(x) paste(x[1], x[2], > sep="")) > [1] "aab" "bab" "cab" "aac" "bac" "cac" "aad" "bad" "cad" > > > clist <- list("AA","BB") > > > apply(expand.grid(alist, blist, clist),1,function(x) paste(x[1], x[2], > x[3], sep="")) > [1] "aabAA" "babAA" "cabAA" "aacAA" "bacAA" "cacAA" "aadAA" "badAA" > "cadAA" "aabBB" > [11] "babBB" "cabBB" "aacBB" "bacBB" "cacBB" "aadBB" "badBB" "cadBB" > > > dlist <- list(TRUE,FALSE) > > > apply(expand.grid(alist, blist, clist, dlist),1,function(x) paste(x[1], > x[2], x[3], (x[4]), sep=""))[8:12] > [1] "badAATRUE" "cadAATRUE" "aabBBTRUE" "babBBTRUE" "cabBBTRUE" > > > This could get unwieldily if the length of the lists are appreciable, since > the number of rows will be the product of all the lengths. On the other hand > you could create a dataframe indexed by the variables in expand.grid's > output: > > > master.df <- data.frame( expand.grid(alist, blist, clist, dlist), > results = apply(expand.grid(alist, blist, > clist,dlist),1, > function(x) paste(x[1], x[2], x[3], > (x[4]), sep=""))) > > > > -- > David Winsemius > > On Dec 22, 2008, at 3:33 PM, Charles C. Berry wrote: > > On Mon, 22 Dec 2008, Brigid Mooney wrote: >> >> Hi All, >>> >>> I'm still pretty new to using R - and I was hoping I might be able to get >>> some advice as to how to use 'apply' or a similar function instead of >>> using >>> nested for loops. >>> >> >> Unfortunately, you have given nothing that is reproducible. >> >> The details of MyFunction and the exact structure of the list objects are >> crucial. >> >> Check out the _Posting Guide_ for hints on how to formulate a question >> that will elecit an answer that helps you. >> >> HTH, >> >> Chuck >> >> >> >>> Right now I have a script which uses nested for loops similar to this: >>> >>> i <- 1 >>> for(a in Alpha) { for (b in Beta) { for (c in Gamma) { for (d in Delta) { >>> for (e in Epsilon) >>> { >>> Output[i] <- MyFunction(X, Y, a, b, c, d, e) >>> i <- i+1 >>> }}}}} >>> >>> >>> Where Output[i] is a data frame, X and Y are data frames, and Alpha, >>> Beta, >>> Gamma, Delta, and Epsilon are all lists, some of which are numeric, some >>> logical (TRUE/FALSE). >>> >>> Any advice on how to implement some sort of solution that might be >>> quicker >>> than these nested 'for' loops would be greatly appreciated. >>> >>> Thanks! >>> >>> [[alternative HTML version deleted]] >>> >>> ______________________________________________ >>> R-help@r-project.org mailing list >>> https://stat.ethz.ch/mailman/listinfo/r-help >>> PLEASE do read the posting guide >>> http://www.R-project.org/posting-guide.html<http://www.r-project.org/posting-guide.html> >>> and provide commented, minimal, self-contained, reproducible code. >>> >>> >> Charles C. Berry (858) 534-2098 >> Dept of Family/Preventive >> Medicine >> E mailto:cberry@tajo.ucsd.edu UC San Diego >> http://famprevmed.ucsd.edu/faculty/cberry/ La Jolla, San Diego >> 92093-0901 >> >> ______________________________________________ >> R-help@r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-help >> PLEASE do read the posting guide >> http://www.R-project.org/posting-guide.html<http://www.r-project.org/posting-guide.html> >> and provide commented, minimal, self-contained, reproducible code. >> > >[[alternative HTML version deleted]]