3
$\begingroup$

Consider the following nested list

x = {{1,2,a}, {3,4,a}, {8,11,b}, {12,3,a}, {4,3,b}, {3,2,c}}

I want to use the categorical variable [a,b,c] in order to group the above sublists (resulting in a list with "3 degrees of nestedness"). For the above example the goal is to obtain:

{ { {1,2},{3,4},{12,3} }, { {8,11},{4,3} }, {3,2} }

, where the first nested sublist is the group of sublists in x that contained the argument a, the second nested sublist is the group of sublists in x that contained the argument b and the third sublist is the group of sublists in x that contained the argument c

$\endgroup$
5
$\begingroup$
x = {{1, 2, a}, {3, 4, a}, {8, 11, b}, {12, 3, a}, {4, 3, b}, {3, 2, c}};

f = Map[Most, GatherBy[#, Last], {2}] &;
(* or f = Most /@ # & /@ GatherBy[#, Last] & *)

f@x
(* {{{1,2},{3,4},{12,3}},{{8,11},{4,3}},{{3,2}}} *)

or

f2 = Map[Most, SplitBy[SortBy[#, Last], Last], {2}] &;
(* or f2 = Map[Most, SplitBy[#[[Ordering[Last /@ #]]], Last], {2}] &; *)

f2@x
(* {{{1,2},{3,4},{12,3}},{{8,11},{4,3}},{{3,2}}} *)

Note: Under this method, the ordering of the elements within each category may change (thanks: @Michael E2).

Version 10:

f3 = Values@GroupBy[#, Last->Most]&
f3@x
(*  {{{1,2},{3,4},{12,3}},{{8,11},{4,3}},{{3,2}}} *)
$\endgroup$
  • $\begingroup$ Note that the two methods are not strictly equivalent. (E.g., try x = {{3, 4, a}, {1, 2, a}, {8, 11, b}, {12, 3, a}, {4, 3, b}, {3, 2, c}}, in which the elements are not ordered by the secondary criteria used by SortBy.) (+1) $\endgroup$ – Michael E2 Dec 4 '14 at 19:59
  • $\begingroup$ @MichaelE2, good point. I updated with a note. $\endgroup$ – kglr Dec 4 '14 at 20:11
2
$\begingroup$
groupCategorically[ll_List, keys_List] := 
 keys /. GroupBy[ll, Last] /. Thread[keys :> Sequence[]]

Example:

groupCategorically[{{1, 2, a}, {3, 4, a}, {8, 11, b}, {12, 
   3, a}, {4, 3, b}, {3, 2, c}}, {a, b, c}]

(* Out[156]= {{{1, 2}, {3, 4}, {12, 3}}, {{8, 11}, {4, 3}}, {{3, 2}}} *)
$\endgroup$
2
$\begingroup$
f[l_List, cats_List] := Cases[l, p : {__, #} :> Most@p] & /@ cats
f[x, {a, b, c}]
(* {{{1, 2}, {3, 4}, {12, 3}}, {{8, 11}, {4, 3}}, {{3, 2}}} *)

It will ignore the "categorical" variables not included:

f[x, {a, b}]
(* {{{1, 2}, {3, 4}, {12, 3}}, {{8, 11}, {4, 3}}}*)
$\endgroup$
1
$\begingroup$
DeleteCases[GatherBy[x, Last], _Symbol, -1]
(*{{{1, 2}, {3, 4}, {12, 3}}, {{8, 11}, {4, 3}}, {{3, 2}}}*)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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