Mathematica, improve speed for appendto in the loo

2019-06-14 08:50发布

问题:

how to improve the following function? currently it is very slow. Thanks in advance.

    discounts[firstDFF_] :=
        Module[ 
            {len = Length[swapdata], running = firstDF, newdisc, disclist = {firstDFF}, k = 2},

            Do[
                newdisc = (1 - swapdata[[k]]*running)/(1 + swapdata[[k]]);

                running += newdisc;

                AppendTo[disclist, newdisc]
                , 
                {k, 1, len}
            ];

            disclist
        ];

it is for getting a list of discount factor during the bootstrapping.

回答1:

The code was sped up from 14.59 seconds to 0.34 seconds simply by using disclist = {disclist, newdisc} with Flatten instead of AppendTo[disclist, newdisc].

Demonstration below. First the OP's original code.

swapdata = ConstantArray[0.03, 100000];

firstDF = 1;

discounts[firstDFF_] := Module[{len = Length[swapdata],
    running = firstDF,
    newdisc,
    disclist = {firstDFF}, k = 2},
   Do[newdisc = (1 - swapdata[[k]]*running)/(1 + swapdata[[k]]);
    running += newdisc;
    AppendTo[disclist, newdisc], {k, 1, len}];
   disclist];

First[{time, result1} = Timing[discounts[100]]]

14.594

discounts[firstDFF_] := Module[{
    len = Length[swapdata],
    running = firstDF,
    newdisc,
    disclist = {firstDFF}, k = 2},
   Do[newdisc = (1 - swapdata[[k]]*running)/(1 + swapdata[[k]]);
    running += newdisc;
    disclist = {disclist, newdisc}, {k, 1, len}];
   Flatten@disclist];

First[{time, result2} = Timing[discounts[100]]]

0.343

result1 == result2

True



回答2:

a couple more ways. These are just slightly faster than ChrisD's Do .. disclist = {disclist, newdisc} ..

discounts[firstDFF_] := 
  Module[{len = Length[swapdata], running = firstDF, newdisc},
   Join[{firstDFF}, Table[
     newdisc = (1 - swapdata[[k]]*(running))/(1 + swapdata[[k]]);
     running += newdisc;
     newdisc, {k, 1, len}]]];
First[{time, result} = Timing[discounts[100]]]

discounts[firstDFF_] := Module[{running = firstDF, newdisc},
   Join[{firstDFF}, (
       newdisc = (1 - #*running)/(1 + #);
       running += newdisc;
       newdisc) & /@ swapdata]];
First[{time, result} = Timing[discounts[100]]]

discounts[firstDFF_] :=
  Reap[Sow[firstDFF];
    Fold[#1 + Sow[(1 - Times@##)/(1 + #2)] &, firstDF  ,
       swapdata]][[2, 1]];
First[{time, result} = Timing[discounts[100]]]