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
    May 27, 2015 at 3:01
  • $\begingroup$ @user170231 Glad I could help! Thank you for the accept. $\endgroup$
    – Ivan
    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
    May 27, 2015 at 6:11
  • $\begingroup$ Why not have the kernel be {1, 1}/2 to begin with? $\endgroup$ 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
    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
    May 27, 2015 at 8:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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