2
$\begingroup$

If the key is string, this code is working

dataset = Dataset[{
    <|"a" -> 1, "b" -> "x"|>,
    <|"a" -> 2, "b" -> "y"|>,
    <|"a" -> 3, "b" -> "z"|>,
    <|"a" -> 4, "b" -> "x"|>,
    <|"a" -> 5, "b" -> "y"|>,
    <|"a" -> 6, "b" -> "z"|>}];
dataset[GroupBy["b"]]

But the key is not always string(such as the result of Counts), for example:

dataset2 = Dataset[{
    <|"a" -> 1, 9 -> "x"|>,
    <|"a" -> 2, 9 -> "y"|>,
    <|"a" -> 3, 9 -> "z"|>,
    <|"a" -> 4, 9 -> "x"|>,
    <|"a" -> 5, 9 -> "y"|>,
    <|"a" -> 6, 9 -> "z"|>}];
dataset2[GroupBy[9]]

As we see, when the key is a digtal 9, the code cannot run normally..How to groupy it in such case?

$\endgroup$
2
$\begingroup$

We must use Key[9] in place of 9:

dataset2[GroupBy[Key[9]]]

dataset screenshot

Note that dataset visualizer does not do a very good job with the result (non-string association keys often confuse it). It is easier to see that we have obtained the correct result by unwrapping the data:

dataset2[GroupBy[Key[9]]] // Normal

(* <| "x" -> {<|"a" -> 1, 9 -> "x"|>, <|"a" -> 4, 9 -> "x"|>}
    , "y" -> {<|"a" -> 2, 9 -> "y"|>, <|"a" -> 5, 9 -> "y"|>}
    , "z" -> {<|"a" -> 3, 9 -> "z"|>, <|"a" -> 6, 9 -> "z"|>}
    |>
*)

Query Operator vs. Normal Function

This is a case where a query operator has different semantics from its liked-named function counterpart.

The normal function GroupBy takes a function argument for grouping purposes. Using the string "b" as a grouping function does not produce a particularly useful result:

dataset // Normal // GroupBy["b"]

(* <| "b"[<|"a" -> 1, "b" -> "x"|>] -> {<|"a" -> 1, "b" -> "x"|>}
    , "b"[<|"a" -> 2, "b" -> "y"|>] -> {<|"a" -> 2, "b" -> "y"|>}
    , "b"[<|"a" -> 3, "b" -> "z"|>] -> {<|"a" -> 3, "b" -> "z"|>}
    , "b"[<|"a" -> 4, "b" -> "x"|>] -> {<|"a" -> 4, "b" -> "x"|>}
    , "b"[<|"a" -> 5, "b" -> "y"|>] -> {<|"a" -> 5, "b" -> "y"|>}
    , "b"[<|"a" -> 6, "b" -> "z"|>] -> {<|"a" -> 6, "b" -> "z"|>}
    |>
*)

When using the GroupBy function, we must use Key["b"] instead of "b":

dataset // Normal // GroupBy[Key["b"]]

(* <| "x" -> {<|"a" -> 1, "b" -> "x"|>, <|"a" -> 4, "b" -> "x"|>}
    , "y" -> {<|"a" -> 2, "b" -> "y"|>, <|"a" -> 5, "b" -> "y"|>}
    , "z" -> {<|"a" -> 3, "b" -> "z"|>, <|"a" -> 6, "b" -> "z"|>}
    |>
*)

By contrast, the GroupBy query operator receives special treatment. The Details section of the Dataset documentation says this:

Syntactic Sugar

Functions such as CountsBy, GroupBy, and TakeLargestBy normally take another function as one of their arguments. When working with associations in a Dataset, it is common to use this "by" function to look up the value of a column in a table.

To facilitate this, Dataset queries allow the syntax "string" to mean Key["string"] in such contexts. For example, the query operator GroupBy["string"] is automatically rewritten to GroupBy[Key["string"]] before being executed.

Similarly, the expression GroupBy[dataset,"string"] is rewritten as GroupBy[dataset,Key["string"]].

It is because of this query syntactic sugar that we can omit the Key[...] wrapper for strings -- and only strings. So in a query we can write GroupBy["b"] but not GroupBy[9].

The moral of this story is that we cannot safely assume that a query operator behaves in exactly the same fashion as a function with the same name.

$\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.