[R] How can I avoid nested 'for' loops or quicken the process?

Daniel Nordlund djnordlund at verizon.net
Tue Dec 23 19:00:47 CET 2008


Avoiding multiple nested for loops (as requested in the subject) is usually
a good idea, especially if you can take advantage of vectorized functions.
You were able redesign your code to use a single for loop.  I presume there
was a substantial improvement in program speed.  How much additional time is
saved by using apply to  eliminate the final for loop?  Is it worth the
additional programming time?  Enquiring minds want to know. :-)

Dan

Daniel Nordlund
Bothell, WA USA  

> -----Original Message-----
> From: r-help-bounces at r-project.org 
> [mailto:r-help-bounces at r-project.org] On Behalf Of Brigid Mooney
> Sent: Tuesday, December 23, 2008 8:36 AM
> To: David Winsemius
> Cc: r-help at r-project.org
> Subject: Re: [R] How can I avoid nested 'for' loops or 
> quicken the process?
> 
> --------------------------------------------------------------
> ----------------------------------------------------------------
> Problem Description:  (reproducible code below)
> --------------------------------------------------------------
> ----------------------------------------------------------------
> I cannot seem to get as.data.frame() to work as I would expect.
> 
>  Results2 seems to contain repeated column titles for each 
> row, as well as a
> row name 'investment' (which is not intended), like:
>  Results2
> [[1]]
>            OutTotInvestment OutNumInvestments OutDolProf OutPerProf
> OutNetGains OutLong OutShort OutInvestment OutStoploss 
> OutComission OutPenny
> OutVolume OutNumU OutAccDefn
> investment            30000                 3       -450     -0.015
> -0.0154    0.75     -0.5         10000      -0.015        2e-04
> 3      0.02       2          0
> [[2]]
>            OutTotInvestment OutNumInvestments OutDolProf OutPerProf
> OutNetGains OutLong OutShort OutInvestment OutStoploss 
> OutComission OutPenny
> OutVolume OutNumU OutAccDefn
> investment            30000                 3       -450     -0.015
> -0.0154     1.5     -0.5         10000      -0.015        2e-04
> 3      0.02       2          0
> ...
> 
> When I try to apply 'as.data.frame', it concatenates 
> incremental numbers to
> the repeated row headers and gives:
> as.data.frame(Results2)
>            OutTotInvestment OutNumInvestments OutDolProf OutPerProf
> OutNetGains OutLong OutShort OutInvestment OutStoploss 
> OutComission OutPenny
> OutVolume OutNumU OutAccDefn
> investment            30000                 3       -450     -0.015
> -0.0154    0.75     -0.5         10000      -0.015        2e-04
> 3      0.02       2          0
>            OutTotInvestment.1 OutNumInvestments.1 
> OutDolProf.1 OutPerProf.1
> OutNetGains.1 OutLong.1 OutShort.1 OutInvestment.1 OutStoploss.1
> OutComission.1 OutPenny.1
> investment              30000                   3         -450
> -0.015       -0.0154       1.5       -0.5           10000
> -0.015          2e-04          3
>            OutVolume.1 OutNumU.1 OutAccDefn.1 OutTotInvestment.2
> OutNumInvestments.2 OutDolProf.2 OutPerProf.2 OutNetGains.2 OutLong.2
> OutShort.2 OutInvestment.2
> investment        0.02         2            0
> 30000                   3         -450       -0.015       -0.0154
> 0.75         -1           10000
> ...
> 
> which is a data frame of dimension 1 224, when I am looking 
> for a data frame
> like Results of dimension 16 14.
> 
> 
> --------------------------------------------------------------
> ----------------------------------------------------------------
> Reproducible code:
> --------------------------------------------------------------
> ----------------------------------------------------------------
> # --------------------------------------------------------------
> # FUNCTION calcProfit
> # --------------------------------------------------------------
> calcProfit <- function(IterParam,  marketData, dailyForecast) #, long,
> short, investment, stoploss, comission, penny, volume, numU, accDefn)
>   {
>     if (class(IterParam) == "numeric")
>       {
>         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"]
>       } else {
>           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)
>   }
> 
> 
> # 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))
>        }
>   }
> 
> 
> Results2 <- apply(CombParam, 1, calcProfit, X, Y)
> 
> --------------------------------------------------------------
> ----------------------------------------------------------------
> 
> On Tue, Dec 23, 2008 at 11:15 AM, David Winsemius 
> <dwinsemius at comcast.net>wrote:
> 
> >
> > On Dec 23, 2008, at 10:56 AM, Brigid Mooney wrote:
> >
> > Thank you again for your help.
> >>
> >> snip
> >
> >>
> >>
> > -------------
> >> With the 'apply' call, Results2 is of class list.
> >>
> >> Results2 <- apply(CombParam, 1, calcProfit, X, Y)
> >>
> >> 
> --------------------------------------------------------------
> -----------------------------------------
> >>
> >> How can I get convert Results2 from a list to a data frame 
> like Results?
> >>
> >
> > Have you tried as.data.frame() on Results2? Each of its 
> elements should
> > have the proper structure.
> >
> > You no longer have a reproducible example, but see this 
> session clip:
> > > lairq <- apply(airquality,1, function(x) x )
> > > str(lairq)
> >  num [1:6, 1:153] 41 190 7.4 67 5 1 36 118 8 72 ...
> >  - attr(*, "dimnames")=List of 2
> >  ..$ : chr [1:6] "Ozone" "Solar.R" "Wind" "Temp" ...
> >  ..$ : NULL
> > > is.data.frame(lairq)
> > [1] FALSE
> > > is.data.frame(rbind(lairq))
> > [1] FALSE
> > > is.data.frame( as.data.frame(lairq) )
> > --
> > David Winsemius
> >
> 
> 	[[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.



More information about the R-help mailing list