Consider the following dataset:
data = Dataset[{ <|"a" -> <|"A" -> 1, "B" -> 2|>, "b" -> <|"X" -> 5, "Y" -> 7|>|>,
<|"a" -> <|"A" -> 4, "B" -> 2|>, "b" -> <|"X" -> 6, "Y" -> 8|>|>,
<|"a" -> <|"A" -> 2, "B" -> 7|>, "b" -> <|"X" -> 3, "Y" -> 1|>|>}]
It has nested fields for grouping, so, for example, we'd access what might be called data[2].b.X
in another language as data[2, "b", "X"]
(to get the value 6
).
In my application, I'm looking to modify each of the values of a given (terminal) field by combining them in a certain way with the values of another (terminal) field. For example, I might want to adjust all the so-called data[].a.B
's by replacing them with data[].a.B - data[].b.Y
.
My first approach was to use the way Datasets allow you to map at a field name. For example, if I wanted to double all of the data[].a.B
's, I could do that with data = data[{All -> {"a" -> {"B" -> (2*# &)}}}]
, which gives me back the original dataset with that 'column' of 1
, 4
, 2
pictured above having become 2
, 8
, 4
.
But to include the field values under b
, this has to become a function of each of the list indices; that is, it needs to become data = data[{All -> somefunction}]
. This function, in turn, involves mapping a function at specific field names of a dataset: each of its arguments is the sub-dataset consisting of a single association (with keys "a"
, "b"
). So to implement data[].a.B - data[].b.Y
, we could try something like
data = data[{All -> Function[a, a[{"a" -> {"B" -> (# - a["b", "X"] &)}}] ] }]
However, this doesn't work! It seems as though you can't nest dataset queries/actions inside things acting on parts of datasets.
Why doesn't this work, and is there a convenient workaround?