Mathematica Stack Exchange is a question and answer site for users of Mathematica. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'd like to get the Min, Max, Median, Mean, etc. for the same list. For now I'm doing the following:

y = {1, 2, 3, 4, 5, 6, 7};
Map[{Max[#] , Min[#] , Median[#], Mean[#]} &, y, {0}]

It seems like there should be a better way, not that this is awful. Is there a cleaner way to do this?

share|improve this question
6  
You are looking for Through: Through[{Max, Min, Median, Mean}[y]]. – Leonid Shifrin Feb 18 at 22:46
1  
A more restricted case of this question: (3127). More advanced questions possibly of interest: (3858), (11298) – Mr.Wizard Feb 19 at 18:20
up vote 21 down vote accepted

Also,

y = {1, 2, 3, 4, 5, 6, 7};

#[y] & /@ {Max, Min, Median, Mean}

(*  {7, 1, 4, 4}  *)

EDIT: comparing the timings:

n = 100000;

Do[Through[{Max, Min, Median, Mean}[y]], n] // AbsoluteTiming

(*  {0.548089, Null}  *)

Do[#[y] & /@ {Max, Min, Median, Mean}, n] // AbsoluteTiming

(*  {0.709574, Null}  *)

Through is more efficient, at least in this case.

share|improve this answer
3  
I use this more often than Through. – Mr.Wizard Feb 19 at 6:42
1  
@Mr.Wizard any reasons, or just personal preference? – LLlAMnYP Feb 19 at 9:33
    
It never occurred to me that I could do that with map. I never put the # in place of a function. In retrospect I don't know why. – Mitchell Kaplan Feb 19 at 12:32
    
@LLlAMnYP I use Map for so much else that it is very familiar, whereas Through still takes a moment of thought. More importantly this works with held arguments, e.g. #[2 + 2] & /@ {Hold, HoldForm, Defer, MakeBoxes}. And as nearly everyone knows I like terse coding and this is a few keystrokes shorter. – Mr.Wizard Feb 19 at 17:54
    
@Mr.W, ahh, how right you are, & has the attribute HoldAll. Convenient. Sometimes, of course, the opposite behavior may be desired. – LLlAMnYP Feb 19 at 17:57

You can use Through.

Through[{Max, Min, Median, Mean}[y]]

(* {7, 1, 4, 4} *)

Hope this helps.

share|improve this answer
3  
I've always had trouble getting the syntax of Through correct, since to me it seems more natural if it were instead Through[{Max, Min, Median, Mean}][y] – murray Feb 19 at 1:49
1  
@murray You can use Prefix if it feels more natural: Through@{Max, Min, Median, Mean}[y] – Edmund Feb 19 at 3:44
    
Thanks! - I had tried through, but I used it wrong. I tried to map or apply it. – Mitchell Kaplan Feb 19 at 12:30

murray wrote:

I've always had trouble getting the syntax of Through correct, since to me it seems more natural if it were instead Through[{Max, Min, Median, Mean}][y]

each[x : _[__]][arg__] := Through[ x @ arg ]

foo // each[bar[a, b, c]]

   (* out:   bar[a[foo], b[foo], c[foo]]   *)

Sequence[foo, bar] // each[{a, b, c}]

   (* out:   {a[foo, bar], b[foo, bar], c[foo, bar]}   *)

I rather like that idea. Thanks, murray.

Comments below Bob Hanlon's answer remind me one thing this lacks as written is the ability to work with held arguments, which #[y] & /@ {f1, f2, . . .} has by nature. If I am going to actually use this abstraction I will need to address that. One possibility:

ClearAll[each]

each[x : _[__]] := Function[, Through @ Unevaluated @ x[##], HoldAll]

Now:

2 + 2 // each[{Hold, HoldForm, Defer, MakeBoxes}]

   (* out:   {Hold[2 + 2], 2 + 2, 2 + 2, RowBox[{2, +, 2}]}  *)

Update: also notably this case which is a bit harder to get with Map:

2 + 2 // each[ Hold[foo, bar, baz] ]

   (* out:   Hold[foo[2 + 2], bar[2 + 2], baz[2 + 2]]   *)
share|improve this answer
1  
I still find the (* ...*) output convention much clearer. – Dr. belisarius Feb 19 at 13:38
1  
@Dr.belisarius I honored your opinion in this answer but I cannot promise that I will change my habit. We'll see. – Mr.Wizard Feb 19 at 18:08
    
Thanks a lot :) – Dr. belisarius Feb 19 at 18:12

Query offers a reasonable syntax for this case:

y = {1, 2, 3, 4, 5, 6, 7};

y // Query[{Max, Min, Median, Mean}]
(* {7, 1, 4, 4} *)

Query has the nice feature that we can apply such lists of functions at deeper levels without too much additional thought:

ys = {{1, 2, 6}, {4, 5, 9}, {10, 20, 60}};

ys // Query[All, {Max, Min, Median, Mean}]
(* {{6, 1, 2, 3}, {9, 4, 5, 6}, {60, 10, 20, 30}} *)
share|improve this answer
1  
I did not realize Query could be used like that! +1 of course. However it is not a general replacement for Through as the output is different, e.g. "x" // Query[{Max, Min, Median, Mean}] returns {"x", "x", Missing["Indeterminate"], Missing["Indeterminate"]}, and it is much slower than Through or Map, undoubtely related to (56609) – Mr.Wizard Feb 19 at 21:05
2  
@Mr.Wizard Your points are absolutely valid, but as usual you and I have different pain thresholds when labelling something as "much slower" :D Using Normal @ Query[...] will eliminate both the semantic differences and the performance differences since the query will then be compiled down to a wafer-thin wrapper over Through (the canonical answer). But I find myself using Query as-is with increasing frequency these days because its one-stop-shopping syntactic convenience usually overshadows the other considerations (for me, YMMV). – WReach Feb 19 at 23:57

I prefer:

{Max[#], Min[#], Median[#], Mean[#]} & @ y

Clean, simple, and elegant.

share|improve this answer

And (so far), no one has suggested the right solution.

If you have a bundle of operations that you want to reuse, define a function.

stats[x_List]:= {Max[#] , Min[#] , Median[#], Mean[#]}& [x]
...

y = {1, 2, 3, 4, 5, 6, 7};
stats[y]
(* {7, 1, 4, 4} *)
share|improve this answer
    
Why not stats[x_List] := #[y] & /@ {Max, Min, Median, Mean}, especially if you want to extend the list of stats? – garej Feb 21 at 7:12
    
@garej: Habit of mind: morphisms go to the left of the objects they act on. (If I were an adherent to certain European algebraist schools, I'd feel the other way about it.) – Eric Towers Feb 21 at 19:19

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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