7
$\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$
  • 1
    $\begingroup$ Mean /@ FoldList[Flatten[{##}] &, A[[All, 2]]] $\endgroup$ – Dr. belisarius Jan 5 '16 at 18:53
  • 2
    $\begingroup$ ReplaceList[A[[All, 2]], {x__, y___} :> Mean@{x}] $\endgroup$ – Dr. belisarius Jan 5 '16 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 '16 at 19:02
  • $\begingroup$ @Sascha No problem :) $\endgroup$ – Dr. belisarius Jan 5 '16 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 '16 at 20:12
7
$\begingroup$
      Accumulate@Last@Transpose[A]/Range@Length@A

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

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

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

enter image description here

$\endgroup$
4
$\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$
  • $\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 '16 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 '16 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 '16 at 9:56
4
$\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$
2
$\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$
1
$\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, privacy policy and cookie policy

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