10

I have a list of the form:

{{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}, {{9, 10}, {11, 12}}}

How can I create a function which will take each set at the highest level of the list:

{{1, 2}, {3, 4}}

{{5, 6}, {7, 8}}

{{9, 10}, {11, 12}}

And subtract the first element of the set from the second element of the set, here:

{3, 4} - {1, 2} = {2, 2}

{7, 8} - {5, 6} = {2, 2}

{11, 12} - {9, 10} = {2, 2}

Then compute the average or median of these values ({2, 2} here in either case)? It's clear how to do this using loops or tables, but is there a simpler way to proceed that makes clever use of Mathematica?

For a table based implementation:

PairList = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}, {{9, 10}, {11, 12}}};
PLMean = Mean[Table[PairList[[u, 2]] - PairList[[u, 1]], {u, 1, Length[PairList]}]]
rm -rf
  • 88,781
  • 21
  • 293
  • 472
user8646
  • 163
  • 4

3 Answers3

17

What about this?:

list = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}, {{9, 10}, {11, 12}}}
Mean[Subtract @@@ Reverse /@ list]

A shorter one:

Mean[Plus[-#, #2] & @@@ list]

A even shorter one:

Mean[#2 - #1 & @@@ list]
xzczd
  • 65,995
  • 9
  • 163
  • 468
10

Also this:

{-1, 1}.Mean@list

or this (looks nicer in the front end):

Mean[{-1, 1}.list\[Transpose]]

It is worth noting that the first form is considerably more time efficient than the second, though both are fast (warning, several GB RAM used):

list = RandomReal[99, {30000000, 2, 2}];

{-1, 1}.Mean@list              // Timing // First

Mean[{-1, 1}.list\[Transpose]] // Timing // First

0.1902

0.921

The second also uses about 2.5X as much memory as figured by MaxMemoryUsed[].

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
Simon Woods
  • 84,945
  • 8
  • 175
  • 324
  • 3
    Simon, I hate you. ;-) (I was sniffing around Dot trying to solve this puzzle and I failed. Well done!) – Mr.Wizard Jul 20 '13 at 12:24
  • @Mr.Wizard Heh heh. For those who like compact code the standard form of Dot must surely rate as one of the best in terms of functionality per pixel. And it's infix... :-) – Simon Woods Jul 22 '13 at 10:12
9

This method should be the most efficient:

Mean[#[[All, 2]] - #[[All, 1]]& @ {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}, {{9, 10}, {11, 12}}}]
{2, 2}

Another method (of many possible) is more complicated and therefore not recommended (I left it here for educational purposes): use Apply at the first level (@@@) this function #2 - #1 & (subtracting first and second elements of lists) and than map (/@) Mean:

Mean /@ Transpose[#2 - #1 & @@@ {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}, {{9, 10}, {11, 12}}}]
{2, 2}
Artes
  • 57,212
  • 12
  • 157
  • 245