[R] How can I avoid nested 'for' loops or quicken the process?
David Winsemius
dwinsemius at comcast.net
Tue Dec 23 16:30:40 CET 2008
On Dec 23, 2008, at 9:55 AM, Brigid Mooney wrote:
> 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
apply is giving calcProfit a named numeric vector and then calcProfit
is trying to parse it with "$" which is an operator for lists. Try
serial corrects of the form:
long <- IterParam["long"]
That seemed to let the interpreter move on to the next error ;-)
> Results2 <- apply(CombParam, 1, calcProfit, X, Y)
Error in IterParam$short : $ operator is invalid for atomic vectors
--
David Winsemius
>
> 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 at 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 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
>
> ______________________________________________
> 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.
>
>
More information about the R-help
mailing list