How to convert a Dataset into an indexed dataset / association-of-associations given a column header?
data = {<|"letter" -> "a", "foo" -> 1, "bar" -> 2|>, <|
"letter" -> "b", "foo" -> 3, "bar" -> 4|>, <|"letter" -> "c",
"foo" -> 5, "bar" -> 6|>};
dataDS = Dataset[data];
ClearAll[f];
f[ds_Dataset, ch_] := ds[Apply[Association], #[ch] -> KeyDrop[#, ch] &];
f[dataDS, "letter"]
(Using the definition suggested by @WReach in the comments.)
First answer
data = {<|"letter" -> "a", "foo" -> 1, "bar" -> 2|>, <|
"letter" -> "b", "foo" -> 3, "bar" -> 4|>, <|"letter" -> "c",
"foo" -> 5, "bar" -> 6|>};
dataDS = Dataset[data];
ClearAll[f];
f[ds_Dataset, ch_] := Dataset@Association@Normal@ds[All, #[ch] -> KeyDrop[#, ch] &];
f[dataDS, "letter"]
ClearAll[f0]
f0 = GroupBy[##, Association @* KeyDrop[#2]] &;
Examples:
ds = Dataset @ {<|"letter" -> "a", "foo" -> 1, "bar" -> 2|>,
<|"letter" -> "b", "foo" -> 3, "bar" -> 4|>,
<|"letter" -> "c", "foo" -> 5, "bar" -> 6|>};
Row[{ds, f0[ds, "letter"], f0[ds, "foo"], f0[ds, "bar"]}, Spacer[10]]
You can also do:
ClearAll[f1]
f1 = #[GroupBy[#2] /* Map[Association @* KeyDrop[#2]]] &;
Row[{ds, f1[ds, "letter"], f1[ds, "foo"], f1[ds, "bar"]}, Spacer[10]]
and
ClearAll[f2]
f2 = #[GroupBy @ #2, All, First @ Normal @ Keys @ KeyDrop @ ##] &;
Row[{ds, f2[ds, "letter"], f2[ds, "foo"], f2[ds, "bar"]}, Spacer[10]]
Related to kglr's answer, here's a slight variation:
ds = Dataset @ {
<|"letter" -> "a", "foo" -> 1, "bar" -> 2|>,
<|"letter" -> "b", "foo" -> 3, "bar" -> 4|>,
<|"letter" -> "c", "foo" -> 5, "bar" -> 6|>
};
groupByKey[ds_, key_String] := GroupBy[ds, Function[Slot[key]] -> KeyDrop[key], First];
groupByKey[ds, "letter"]
Of course, you have to be confident that the key values you're grouping by is actually unique, otherwise you'll be dropping rows.