4
$\begingroup$

I have the following dataset:

dataset = Dataset[
  {
   <|"Year" -> 1, 
    "Dataset" ->
     <|
      
      "a" -> <|"x" -> 2559014, "y" -> 756672|>,
      "b" -> <|"x" -> 620783, "y" -> 550642|>,
      "c" -> <|"x" -> 91468, "y" -> 129662|>
      |>
    |>,
   <|"Year" -> 2, 
    "Dataset" ->
     <|
      
      "a" -> <|"x" -> 2693402, "y" -> 766245|>,
      "b" -> <|"x" -> 598006, "y" -> 478835|>,
      "c" -> <|"x" -> 161606, "y" -> 165458|>
      |>
    |>,
   <|"Year" -> 3, 
    "Dataset" ->
     <|
      
      "a" -> <|"x" -> 2757333, "y" -> 791200|>,
      "b" -> <|"x" -> 582524, "y" -> 483263|>,
      "c" -> <|"x" -> 167925, "y" -> 135506|>
      |>
    |>
   }
  ]

I would like to divide the individual "x" and "y" values for each "a", "b", and "c" for each "Year" by the totals I get across the "a", "b", and "c" grouping.

I know I can get the total across the "a", "b", and "c" grouping by using:

dataset[All, All, Total, All]

but I don't know how to divide in the way that I want. The manual result would look like the following:

dataset = Dataset[
  {
   <|"Year" -> 1, 
    "Dataset" ->
     <|
      
      "a" -> <|"x" -> 2559014/3271265, "y" -> 756672/1436976|>,
      "b" -> <|"x" -> 620783/3271265, "y" -> 550642/1436976|>,
      "c" -> <|"x" -> 91468/3271265, 
        "y" -> 129662/1436976|>
      |>
    |>,
   <|"Year" -> 2, 
    "Dataset" ->
     <|
      
      "a" -> <|"x" -> 2693402/3453014, "y" -> 766245/1410538|>,
      "b" -> <|"x" -> 598006/3453014, "y" -> 478835/1410538|>,
      "c" -> <|"x" -> 161606/3453014, 
        "y" -> 165458/1410538|>
      |>
    |>,
   <|"Year" -> 3, 
    "Dataset" ->
     <|
      
      "a" -> <|"x" -> 2757333/3507782, "y" -> 791200/1409969|>,
      "b" -> <|"x" -> 582524/3507782, "y" -> 483263/1409969|>,
      "c" -> <|"x" -> 167925/3507782, 
        "y" -> 135506/1409969|>
      |>
    |>
   }
  ]
```
$\endgroup$
1
  • $\begingroup$ Note that dataset[ All, All, Total ] suffices to get totals across "a", "b", "c" (at least in v12.3.1). $\endgroup$
    – gwr
    Oct 11, 2021 at 10:49

2 Answers 2

5
$\begingroup$

You may use MapIndexed.

With

total = dataset[All, All, Total]

Mathematica graphics

then

MapIndexed[
 {val, index} |-> val/total[Sequence @@ Delete[index, 3]]
 , dataset
 , {4}
 ]

Mathematica graphics

The mapping targets elements at level 4 only. Since total has aggregated over the third key of dataset then the third key of index is removed to reference the total.

Hope this helps.

$\endgroup$
1
  • 1
    $\begingroup$ Here, as commented above, total = dataset[ All, All, Total ] will suffice. $\endgroup$
    – gwr
    Oct 11, 2021 at 11:03
5
$\begingroup$

Here is a way that uses query operators and functional style:

dataset[
  All
, {"Dataset" -> {Total/*Curry[Divide], All} /* Apply[Map]}
]

Dataset

Note: Curry is deprecated in favour of OperatorApplied in the most recent versions of Mathematica.

$\endgroup$
1
  • $\begingroup$ Will take a closer look at this. Thanks. $\endgroup$
    – Edmund
    Oct 23, 2021 at 20:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.