8
$\begingroup$

For a list of any given length, I want to generate another list from it adding elements which are mean of the consecutive elements, in between the elements, of the original list. For example:

list = {a, b, c};
newlist = {a, (a+b)/2, b, (b+c)/2, c}

I have written this function which does the job but I need much more elegant solution:

intFunc[list_] := Module[{list1},
list1 = ConstantArray[0, 2*Length[list] - 1];
Table[list1[[2*i - 1]] = list[[i]], {i, 1, Length[list]}];
Table[list1[[2*i]] = (list[[i]] + list[[i + 1]])/2, {i, 1, Length[list] - 1}];
list1
];
$\endgroup$
4
  • 2
    $\begingroup$ This is not exactly what you want, but do you know ArrayResample? Try: ArrayResample[{a,b,c},5] $\endgroup$ Commented Sep 21, 2015 at 12:17
  • $\begingroup$ I added parentheses where I think you forgot to do so. Please correct me if I were wrong. $\endgroup$
    – yohbs
    Commented Sep 21, 2015 at 12:19
  • $\begingroup$ @MarkusRoellig I'll look into it. $\endgroup$
    – mrkbtr
    Commented Sep 21, 2015 at 12:33
  • $\begingroup$ @yohbs thanks for the correction $\endgroup$
    – mrkbtr
    Commented Sep 21, 2015 at 12:34

3 Answers 3

7
$\begingroup$
intFunc[list_]:=Interpolation[list, InterpolationOrder->1]@Range[1, Length@list, 1/2]
$\endgroup$
1
  • $\begingroup$ Looks good. Thanks! $\endgroup$
    – mrkbtr
    Commented Sep 21, 2015 at 12:35
9
$\begingroup$

My take:

list = {a, b, c};
Riffle[list, MovingAverage[list, 2]]
(* {a, (a + b)/2, b, (b + c)/2, c} *)

Equivalently:

MovingAverage[Riffle[list, list], 2]

Finally, can be generalized to multiple points in between original data points. Equivalent to previous solutions (if using n=2):

intList[list_, n_] := MovingAverage[Flatten[Transpose[ConstantArray[list, n]], 1], n]

Demo (offsets in data include for clarity):

list = {1, 4, 9};
ListPlot[Evaluate @ (#/2 + intList[list, #] & /@ Range[5]), DataRange -> {1, 3}]

demo

Re the comment by Markus Roellig: using ArrayResample like so gives the same results.

intList2[list_, n_] := ArrayResample[list, (Length[list] - 1)*n + 1]
$\endgroup$
2
  • $\begingroup$ Works well. Thanks. $\endgroup$
    – mrkbtr
    Commented Sep 21, 2015 at 13:20
  • $\begingroup$ @mrkbtr added an extension for multiple datapoints in between the original points, in case you might need that. $\endgroup$
    – LLlAMnYP
    Commented Sep 21, 2015 at 13:23
5
$\begingroup$

For integer lists, this s/b nicely faster than others (interpolation and the two moving-average based solutions:

Riffle[#, Divide[Most@# + Rest@#, 2]] &

enter image description here

On real/symbolic, it is comparable to the moving-average based solutions. The interpolation based solution performs uniformly poorly on large lists regardless of type.

$\endgroup$
3
  • $\begingroup$ Perhaps you meant Riffle[#, Divide...] & rather than Riffle[list, Divide...]& ? $\endgroup$
    – LLlAMnYP
    Commented Sep 22, 2015 at 9:55
  • $\begingroup$ @LLlAMnYP oops, yes, fixing. Thanks for catching. $\endgroup$
    – ciao
    Commented Sep 22, 2015 at 10:09
  • $\begingroup$ On my machine with a list of 4*^6 reals your solution still performs a factor of 2 better than the second best. $\endgroup$
    – LLlAMnYP
    Commented Sep 22, 2015 at 10:12

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.