9

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?

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
user170231
  • 1,611
  • 1
  • 11
  • 17

4 Answers4

15
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

kglr
  • 394,356
  • 18
  • 477
  • 896
13
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}
xyz
  • 605
  • 4
  • 38
  • 117
Ivan
  • 2,207
  • 15
  • 25
13

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}

RunnyKine
  • 33,088
  • 3
  • 109
  • 176
7

This seems pretty speedy:

With[{l = Divide[#, 2]}, Append[Most@l + Rest@l, Plus @@ l[[{1, -1}]]]] &
ciao
  • 25,774
  • 2
  • 58
  • 139