8
$\begingroup$

The problem I have is really basic but I just can't get my head around it.

Suppose I have a list of ordered pairs

A = {{a, b}, {c, d}, {e, f}, {g, h}, ...}.

I am looking for a function that will give me the average of partial sums of the second element of each pair, like so:

f[1] = b/1 = A[[1, 2]]/1
f[2] = (b+d)/2 = (A[[1, 2]] + A[[2, 2]])/2
f[3] = (b+d+f)/3 = (A[[1, 2]] + A[[2, 2]] + A[[3, 2]])/3
....
f[n] = ?

Thank you for your help.

$\endgroup$
6
  • 1
    $\begingroup$ Mean /@ FoldList[Flatten[{##}] &, A[[All, 2]]] $\endgroup$ Jan 5, 2016 at 18:53
  • 2
    $\begingroup$ ReplaceList[A[[All, 2]], {x__, y___} :> Mean@{x}] $\endgroup$ Jan 5, 2016 at 18:59
  • $\begingroup$ @Dr. belisarius. Sorry, I didn't intend to rip off your first comment in my answer. You should post your second comment as answer though, since it is very readable. $\endgroup$
    – Sascha
    Jan 5, 2016 at 19:02
  • $\begingroup$ @Sascha No problem :) $\endgroup$ Jan 5, 2016 at 19:03
  • 1
    $\begingroup$ note the best approach may differ if the list is large and you just want a particular n vs if you want to tabulate f for all n.. $\endgroup$
    – george2079
    Jan 5, 2016 at 20:12

6 Answers 6

8
$\begingroup$
      Accumulate@Last@Transpose[A]/Range@Length@A

{b, (b + d)/2, 1/3 (b + d + f), 1/4 (b + d + f + h)}

$\endgroup$
1
  • $\begingroup$ Best answer so far in terms of readability and simplicity. I didn't know about Accumulate, thanks! $\endgroup$
    – Sascha
    Jan 5, 2016 at 20:54
5
$\begingroup$
list = {{a, b}, {c, d}, {e, f}, {g, h}};

Mean[Take[Last /@ list, #]] & /@ Range@Length@list

enter image description here

$\endgroup$
5
$\begingroup$
Clear[f,g, list];
list= {{a,b}, {c, d}, {e, f}, {g, h}}

f[list_,n_]:=Part[FoldList[Plus,Last@Transpose@list] / Range@Length@list, n]

or another version I personally prefer (sadly no operator forms for FoldList and Part)

g[list_, n_]:=list //Transpose
                   //Last
                   //FoldList[Plus, #]& 
                   //Divide[#,Range@Length@list]& 
                   //Extract[n]

I especially like that one can out-comment or partially copy the function definition to find out what the function does step by step

Edit: Instead of //Extract[n] previously //Part[#,n]& was used in the definition of g. Without regard for a potential difference in performance I now like Extract[n] better.

$\endgroup$
3
  • $\begingroup$ I remember someone else proposing and/or supporting this use of post-fix notation. Did you arrive at this style yourself or did you read a post or paper recommending it? (I ask because I'd like to re-read that but I cannot find it.) $\endgroup$
    – Mr.Wizard
    Jan 6, 2016 at 8:11
  • $\begingroup$ @Mr.Wizard. I saw this form first in @Simon Woods answer to this question on the use of the new operator forms. The formatting of g I choose first since not all postfix-operators fit into a single line. In retrospective this may make it even more readable for people that are familiar with imperative programming style. $\endgroup$
    – Sascha
    Jan 6, 2016 at 9:16
  • $\begingroup$ @Mr.Wizard I think I found the blog post you were referring to in your comment (had not seen it before though). It was postet as a comment to your answer in the same question that I linked in my previous comment. Here it is $\endgroup$
    – Sascha
    Jan 6, 2016 at 9:56
5
$\begingroup$

Just to give one more solution: One can use the Accumulate function here, which sums up the parts, then take the Mean (simply by dividing). So I think with

list = {{a, b}, {c, d}, {e, f}, {g, h}}

the command

Accumulate @ list[[All, 2]] / Range[Length@list]

will do the job.

$\endgroup$
3
$\begingroup$

A solution that does not make use of the length of the list and calculates for the whole list.

m = MapAt[Mean, {2 ;;}]@FoldList[Flatten@*List, list[[All, 2]]]
(* {b, (b + d)/2, 1/3 (b + d + f), 1/4 (b + d + f + h)} *)

If you need to just calculate for a particular $n$ then

n = 2;
Mean[list[[1 ;; n, 2]]]
(* (b + d)/2 *)

Hope this helps.

$\endgroup$
2
$\begingroup$

So many roads to Rome...

list = {{a, b}, {c, d}, {e, f}, {g, h}};

MapIndexed[Divide[#1, #2] &, Accumulate[(Last /@ list)]] // Flatten

(*{b, (b + d)/2, 1/3 (b + d + f), 1/4 (b + d + f + h)}*)
$\endgroup$

Your Answer

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

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