1

I have a data set in the following format:

SomeData = {{a, 1, 2}, {b, 2, 3}, {c, 3, 4}, {b, 1, 9}, 
{c, 1, 10}, {a, 2, 3}, {a, 3, 8}, {b, 3, 4}, {c, 2, 9}};

The first element in the sublist is a category while the second element is an index. The third element is a numeric quantity.

My goal is to create a list of lists where each sublist is a collection based on the category and each sublist is sorted by the index. Here is the expected output:

{{{a, 1, 2}, {a, 2, 3}, {a, 3, 8}}, {{b, 1, 9}, {b, 2, 3}, 
{b, 3, 4}}, {{c, 1, 10}, {c, 2, 9}, {c, 3, 4}}}

There are two approaches to the problem: GatherBy first and then SortBy or SortBy then GatherBy.

If I do the SortBy first, I receive the expected results:

GatherBy[SortBy[SomeData, {#[[1]], #[[2]]} &], #[[1]] &]

However, if I try it the other approach, I receive an error:

Map[SortBy[# &, #[[2]] &], GatherBy[SomeData, #[[1]] &]]

Error:

Part::partw: Part 2 of #1 does not exist. >>

UPDATE:

As wxffles points out, I have a simple syntax error in my Map function above. The correct code should be:

Map[SortBy[#, #[[2]] &] &, GatherBy[SomeData, #[[1]] &]]

END UPDATE

If I perform the GatherBy alone and inspect the first element:

GatherBy[SomeData, #[[1]] &][[1]]

We see (yes, it is sorted because my example data was sorted for category a):

{{a, 1, 2}, {a, 2, 3}, {a, 3, 8}}

Using the SortBy for just the first element works as well:

SortBy[GatherBy[SomeData, #[[1]] &][[1]], #[[2]] &]

In short, the problem lies in my using Map and SortBy together. Any ideas?

  • Welcome to Mathematica.SE! I suggest the following: 0) Browse the common pitfalls question 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Read the [faq]! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! – Dr. belisarius Feb 18 '15 at 19:43
  • You have an ampersand in the wrong place. You need SortBy[# , #[[2]] &]& – wxffles Feb 18 '15 at 19:50
  • Wow. Thank you very much for catching that. I guess when you stare at a piece of code so long your mind sees what it wants to. That indeed fixed the problem, and now I feel silly for asking since it was a simple syntax error. Thank you again for the help. – MathematicaUser71 Feb 18 '15 at 19:55

1 Answers1

1

If you are using Mathematica 10 or later operator forms reduce the complexity of your syntax thereby reducing the chance for mistakes. Note that Function is eliminated here:

SortBy[Extract[2]] /@ GatherBy[SomeData, First]
{{{a, 1, 2}, {a, 2, 3}, {a, 3, 8}},
 {{b, 1, 9}, {b, 2, 3}, {b, 3, 4}},
 {{c, 1, 10}, {c, 2, 9}, {c, 3, 4}}}

Since Sort will by default tie-break lists of identical length on an element-wise basis you could also do this:

Sort[SomeData] ~SplitBy~ First
{{{a, 1, 2}, {a, 2, 3}, {a, 3, 8}},
 {{b, 1, 9}, {b, 2, 3}, {b, 3, 4}},
 {{c, 1, 10}, {c, 2, 9}, {c, 3, 4}}}
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371