6
$\begingroup$

I'm looking at the results of the 2015 UK general election

ukp2015raw = Import["http://researchbriefings.files.parliament.uk/documents/CBP-7186/hocl-ge2015-results-full.csv", "CSV"];

Which I choose to store as a Dataset

ukp2015 = Dataset@Map[AssociationThread[ukp2015raw[[1]] -> #] &, ukp2015raw[[2 ;;]]];

To get the most voted candidate for of each constituency I use GroupBy and MaximalBy

ukp2015[GroupBy["constituency_name"], MaximalBy["votes"]]

Which gives the correct answer. But, I would have expected the same output from

ukp2015[GroupBy["constituency_name"], MaximalBy[#, "votes"] &]

Why do I get a different answer from the later?

(Using Mathematica 11.1.0.0 on Windows 7 Pro SP1 64 bits)

Ultimately I would want to select all constituencies where party X won, but party Y or Z would have won if Y and Z selectively dropped candidates and a given percentage of votes are inherited. The thing is that the Select statements get complicated by the fact that MaximalBy[#, "votes"] & doesn't give me the expected output.

$\endgroup$
  • 4
    $\begingroup$ You're right, the answer is not the same. I am not really a great fan of these generalizations of Dataset. MaximalBy should have a function as the second argument and "votes" is of course not a function. Normally MaximalBy["votes"] doesn't work, but Dataset/Query treat it specially and make it work. Then I have to remember which exact functions are treated specially ... What makes it even more confusing is that using "votes" where a function is expected does not cause an error because Mathematica can't really tell what is a "function". Any expression can be used with arguments. $\endgroup$ – Szabolcs Apr 24 '17 at 11:29
  • 3
    $\begingroup$ I think the clearest thing to do is to use a proper function: use #votes& instead of "votes". $\endgroup$ – Szabolcs Apr 24 '17 at 11:29
  • 4
    $\begingroup$ I think this is the relevant line in the Query documentation (under Details): The syntax GroupBy["string"] can be used as a synonym for GroupBy[Key["string"]]. The same syntax is also available for SortBy, CountsBy, MaximalBy, MinimalBy, and DeleteDuplicatesBy. Implicitly, then GroupBy[..., "string"] cannot be used as such a synonym. $\endgroup$ – Szabolcs Apr 24 '17 at 11:37
  • 2
    $\begingroup$ Key["thing"] is a function that can be applied to an association: Key["a"][<|"a" -> 1, "b" -> 2|>]. It is equivalent to #thing&. $\endgroup$ – Szabolcs Apr 24 '17 at 14:32
  • 3
    $\begingroup$ I do not think that this should be closed. I was confused too. $\endgroup$ – Szabolcs Apr 24 '17 at 14:38
9
$\begingroup$

Generally, fun in

MaximalBy[fun]

or

MaximalBy[list, fun]

must be a function. But Query and Dataset are special, and they accept a column name (or generally: association key) in MaximalBy as well as some other functions when using them in their operator form. From the Query documentation:

The syntax GroupBy["string"] can be used as a synonym for GroupBy[Key["string"]]. The same syntax is also available for SortBy, CountsBy, MaximalBy, MinimalBy, and DeleteDuplicatesBy.

Note that here Key["string"] is an operator:

Key["b"][<|"a" -> 1, "b" -> 2|>]
(* 2 *)

This shorthand notation can only be used with operator forms such as MaximalBy["string"], but not general forms like MaximalBy[..., "string"]. The latter will try to apply "string" as a function. This is why these two forms did not give you the same result.

Solution

Instead of using this shorthand, specify an explicit function in MaximalBy. Either Key["votes"] or #votes & will work:

MaximalBy[#votes &]

MaximalBy[#, Key["votes"]]&

MaximalBy[#, #votes &] &
$\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.