5
$\begingroup$

The documentation for GroupBy includes the following cases, among others:

GroupBy[{elem1elem2, … }, {fs1fs2, … }]
groups into nested associations using fsi at level i.

GroupBy[{elem1elem2, … }, spec, red]
applies the function red to reduce lists of values that are generated.


Now, when the spec argument in the second form is a list of functions {f1, …, fn}, IOW, in the case of a n-level grouping, it only makes sense that the red argument be applied at the n-th level of the resulting association, since this is the level where the "lists of values that are generated" end up.

Contrary to this expectation, the red argument always gets applied at the first level, even in the case of multi-level groupings.


For example, the 2-level GroupBy below fails with Lists of unequal length errors.

data = BlockRandom[SeedRandom[1]; RandomInteger[{1, 1000}, 50]];
GroupBy[data, {Mod[#, 5] == 0 &, Mod[#, 6] == 0 &}, Total]

Is there some general way to specify the red argument so that it behaves properly in all cases?

$\endgroup$

2 Answers 2

3
$\begingroup$
GroupBy[data, {Mod[#, 5] == 0 &, Mod[#, 6] == 0 &}, Map[Total, #, {-2}]&]

<|True -> <|False -> 4605, True -> 2400|>, False -> <|False -> 13180, True -> 2946|>|>

GroupBy[data, {Mod[#, 5] == 0&, Mod[#, 6] == 0&, Mod[#, 7] == 0&}, Map[Total, #, {-2}] &]

<|True -> <|True -> <|False -> 1770, True -> 630|>,
False -> <|False -> 4150, True -> 455|>|>,
False -> <|True -> <|False -> 2778, True -> 168|>,
False -> <|False -> 11591, True -> 1589|>|>|>

GroupBy[data, {Mod[#, 5] == 0&, Mod[#, 6] == 0&, Mod[#, 7] == 0&}, Map[Max, #, {-2}] &]

<|True -> <|True -> <|False -> 990, True -> 630|>, False -> <|False -> 965, True -> 385|>|>,
False -> <|True -> <|False -> 822, True -> 168|>, False -> <|False -> 989, True -> 826|>|>|>

$\endgroup$
2
$\begingroup$

you can use the red form to effectively nest the GroupBy , and then finally a red application at the last level.

data = BlockRandom[SeedRandom[1]; RandomInteger[{1, 1000}, 50]];
GroupBy[data, Mod[#, 5] == 0 &,
  GroupBy[#, Mod[#, 6] == 0 &, Total] &]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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