7

Possible Duplicate:
How to Map a subset of list elements to a function?

I want to evaluate a function using arguments from a sliding window over a list.

As an example, lets use Mean as the function, window size as 3, and the list as Range[1, 10].

The results I am looking for are:

{ Mean[{1,2,3}], Mean[{2,3,4}], ... Mean[{8,9,10}] }

i.e.

{2, 3, 4, 5, 6, 7, 8, 9}

Is there something in Mathematica that can do this, or an improvement on the following implementations?


Implementation #1

Slide1[f_, expr_, n_Integer] :=
  Module[{myExpr},
   myExpr = RotateRight[expr, 1];
   Nest[
    Delete[#, -1] &,
    Map[(
       myExpr = RotateLeft[myExpr, 1];
       f[myExpr[[1 ;; n]]]
       ) &, myExpr],
    n - 1]
   ];

In[]:=  Slide1[Mean, Range[1, 10], 3]
Out[]:= {2, 3, 4, 5, 6, 7, 8, 9}

Rotating can not be that efficient, can it?

In[]:=  AbsoluteTiming[Slide1[Mean, Range[1, 100000], 3]][[1]]
Out[]:= 3.529240

Implementation #2

Slide2[f_, expr_, n_Integer] :=
 Module[{result, i},
  result = {};
  For[i = 1, i <= Length[expr] - n + 1, i++,
   AppendTo[result, f[expr[[i ;; i + n - 1]]]];
   ];
  result
  ]

In[]:=  Slide2[Mean, Range[1, 10], 3]
Out[]:= {2, 3, 4, 5, 6, 7, 8, 9}

Please ... For and AppendTo

In[]:=  AbsoluteTiming[Slide2[Mean, Range[1, 100000], 3]][[1]]
Out[]:= 27.811511
mmorris
  • 1,172
  • 7
  • 18
  • I think this is a duplicate of: http://mathematica.stackexchange.com/q/4061/121 (Admittedly better written, but still a duplicate.) – Mr.Wizard May 11 '12 at 21:29
  • I concur (the part about being a duplicate question). A "subset", "sliding window over a list", or in Mathematica speak, a "sublist" are the same thing. Just did not show up in my query. – mmorris May 11 '12 at 21:46
  • mmorris, is it OK with you if I close this question? – Mr.Wizard May 11 '12 at 21:48
  • @Mr.Wizard: I like this question better, since OP showed some legwork, making this a better example of questions we'd like to see. How about closing the older one as a dupe of this instead? – J. M.'s missing motivation May 14 '12 at 13:06
  • @J.M. as I acknowledged I think this one is better, but I don't like the precedent it sets if we start closing older questions. I think the correct action is to edit the older question to make it higher quality. – Mr.Wizard May 14 '12 at 13:14
  • 1
    I have no problem with closing this one – mmorris May 14 '12 at 15:06

4 Answers4

8

There is a function exactly for this: Developer`PartitionMap:

Developer`PartitionMap[f, {1, 2, 3, 4, 5, 6}, 3, 1]
(* {f[{1, 2, 3}], f[{2, 3, 4}], f[{3, 4, 5}], f[{4, 5, 6}]} *)

The first argument to Developer`PartitionMap is the function that's being used (f) and all successive arguments and options are exactly the same as in Partition.

rm -rf
  • 88,781
  • 21
  • 293
  • 472
7

For something more general.

movingMap[f_, data_, r_] := 
  ListConvolve[ConstantArray[1, r], data, {-1, 1}, {}, Times, f@{##} &]

movingMap[Mean, Range[10], 3]

==> {2, 3, 4, 5, 6, 7, 8, 9}
Andy Ross
  • 19,320
  • 2
  • 61
  • 93
6

Why not just

slide3[f_, expr_, n_Integer] :=   f /@ Partition[expr, n, 1];
Leonid Shifrin
  • 114,335
  • 15
  • 329
  • 420
1

You can try

MovingAverage[Range[1,10],3]
chuy
  • 11,205
  • 28
  • 48