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$ Commented Jan 5, 2016 at 18:53
  • 2
    $\begingroup$ ReplaceList[A[[All, 2]], {x__, y___} :> Mean@{x}] $\endgroup$ Commented 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$ Commented Jan 5, 2016 at 19:02
  • $\begingroup$ @Sascha No problem :) $\endgroup$ Commented 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$ Commented 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$ Commented 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$ Commented 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$ Commented 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$ Commented 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$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.