9
$\begingroup$

Is there any way to take the average of pairwise elements in a list?

Example: Given the list

list = {a,b,c}

I'd like to generate the list

{(a+b)/2, (b+c)/2, (a+c)/2}

In this case, MovingAverage almost does the job with the exception of averaging a and c. Adding a at the end of list does the job, but what if I absolutely have to preserve the contents of list?

$\endgroup$

4 Answers 4

13
$\begingroup$
list = {a, b, c};
Append[MovingAverage[list, 2], Mean[{First[list], Last[list]}]]
{(a+b)/2, (b+c)/2, (a+c)/2}

You can define a function if you want:

newMovingAverage[list_] := Append[MovingAverage[list, 2], Mean[{First[list], Last[list]}]]

newMovingAverage[list]
{(a+b)/2, (b+c)/2, (a+c)/2}
$\endgroup$
2
  • $\begingroup$ Ah nice, that was fast! Thanks to both answers! $\endgroup$
    – user170231
    Commented May 27, 2015 at 3:01
  • $\begingroup$ @user170231 Glad I could help! Thank you for the accept. $\endgroup$
    – Ivan
    Commented May 27, 2015 at 3:25
15
$\begingroup$
list = {a, b, c};

Mean[{#, RotateLeft@#}]& @ list
Mean /@ Partition[#, 2, 1 , 1]& @ list
Developer`PartitionMap[Mean, #, 2, 1, 1]& @ list
MovingAverage[ArrayPad[#, {0, 1}, "Periodic"], 2]& @ list
MovingAverage[PadRight[#, 1 + Length@#, #], 2]& @list
({##} + { ##2, #})/2 & @@ list
{(a + b)/2, (b + c)/2, (a + c)/2}

Perfomance Comparison

sol1 = Mean[{#, RotateLeft@#}] &;
sol2 = Mean /@ Partition[#, 2, 1, 1] &;
sol3 = Developer`PartitionMap[Mean, #, 2, 1, 1] &;
sol4 = MovingAverage[ArrayPad[#, {0, 1}, "Periodic"], 2] &;
sol5 = MovingAverage[PadRight[#, 1 + Length@#, #], 2] &;
sol6 = .5 ({##} + {##2, #}) & @@ # &;
RunnyKine = .5 ListCorrelate[{1, 1}, #, 1] &;
Ivan = Append[MovingAverage[#, 2], Mean[{First[#], Last[#]}]] &;

timing[func_, n_] :=
  First@(AbsoluteTiming[func[RandomReal[{1, 10}, 10^n]]])

Test

Table[timing[func, #] & /@ 
  Range[7], {func, {sol1, sol2, sol3, sol4, sol5, sol6, RunnyKine,Ivan}}];

ListLinePlot[%, PlotRange -> {{0, 7}, {0, 12}}, 
  AxesLabel -> {"n", "time"}, 
  PlotLegends -> {"sol1", "sol2", "sol3", "sol4", "sol5", "sol6", 
   "RunnyKine","Ivan"}
]

enter image description here

$\endgroup$
13
$\begingroup$

One can also use ListCorrelate or ListConvolve which I expect to be quick:

1/2 ListCorrelate[{1, 1}, list, 1]

Gives:

{(a + b)/2, (b + c)/2, (a + c)/2}

$\endgroup$
3
  • $\begingroup$ That's the way to do it if speed is needed....+1 $\endgroup$
    – ciao
    Commented May 27, 2015 at 6:11
  • $\begingroup$ Why not have the kernel be {1, 1}/2 to begin with? $\endgroup$ Commented May 27, 2015 at 8:28
  • $\begingroup$ @J. M. That was my initial kernel, I tried the current one for speed gains but noticed there weren't any. I just decided this one looked cleaner to me. $\endgroup$
    – RunnyKine
    Commented May 27, 2015 at 13:31
7
$\begingroup$

This seems pretty speedy:

With[{l = Divide[#, 2]}, Append[Most@l + Rest@l, Plus @@ l[[{1, -1}]]]] &
$\endgroup$
1
  • $\begingroup$ Nicely done and quite speedy. $\endgroup$
    – RunnyKine
    Commented May 27, 2015 at 8:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.