I think you want a nested GroupBy
:
tdsMeans = tds[GroupBy["series"], GroupBy["trial"], Mean /* toKey["mean"], "val"]
using the helper operator:
toKey[k_][v_] :=Association[k= Association[k ->v]> v]
EDIT
To address OP's comment re: ungrouping nested associations for further processing.
There are currently gaps in the language but using some 1-liners can help. for example here ungrouping using the helper associationSerialize
:
tdsMeans[associationSerialize] (* normalized view *)
{{a,1,mean,0.99154},{a,2,mean,2.00269},{a,3,mean,2.99486},{a,4,mean,4.00244},{b,1,mean,0.998718},{b,2,mean,1.99119},{b,3,mean,2.99064},{b,4,mean,4.00225}}
The "mean" can be projected out beforehand:
tdsMeans[All, All, Values][associationSerialize]
Implementation:
associationSerialize=associationFlattenassociationSerialize = associationFlatten /*KeyValueMap[List* KeyValueMap[List /*Flatten]* Flatten]
associationFlatten[as_Association] :=Map[keyFlatten= Map[keyFlatten, as, {0,\[Infinity] ∞}]
keyFlatten[as_Association] :=Association[Flatten[Map[Normal][KeyValueMap[List= Association[Flatten[Map[Normal][KeyValueMap[
List /*Replace[* Replace[{{a_, b_Association} :>KeyMap[> KeyMap[{a, #1} &, b], {a_, b_} :>Association[a>
Association[a ->b]> b]}]][as]]]]
keyFlatten[l_List] :=l= l
keyFlatten[a_ /;AtomQ[a]]; AtomQ[a]] :=a= a
(extra characters since all I did was fix a typo)