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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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