8

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.

Sascha
  • 8,459
  • 2
  • 32
  • 66
drabus
  • 427
  • 3
  • 9

6 Answers6

8
      Accumulate@Last@Transpose[A]/Range@Length@A

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

george2079
  • 38,913
  • 1
  • 43
  • 110
  • Best answer so far in terms of readability and simplicity. I didn't know about Accumulate, thanks! – Sascha Jan 05 '16 at 20:54
5
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.

Sascha
  • 8,459
  • 2
  • 32
  • 66
  • 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.) – Mr.Wizard Jan 06 '16 at 08:11
  • @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. – Sascha Jan 06 '16 at 09:16
  • @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 – Sascha Jan 06 '16 at 09:56
5
list = {{a, b}, {c, d}, {e, f}, {g, h}};

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

enter image description here

eldo
  • 67,911
  • 5
  • 60
  • 168
5

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.

mgamer
  • 5,593
  • 18
  • 26
3

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.

Edmund
  • 42,267
  • 3
  • 51
  • 143
2

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)}*)
Zviovich
  • 9,308
  • 1
  • 30
  • 52