3

I have the following association :

dat = <|"(1)" -> <|"A" -> -1, "B" -> -1, "C" -> -1|>, 
"a" -> <|"A" -> 1, "B" -> -1, "C" -> -1|>, 
"b" -> <|"A" -> -1, "B" -> 1, "C" -> -1|>, 
"ab" -> <|"A" -> 1, "B" -> 1, "C" -> -1|>, 
"c" -> <|"A" -> -1, "B" -> -1, "C" -> 1|>, 
"ac" -> <|"A" -> 1, "B" -> -1, "C" -> 1|>, 
"bc" -> <|"A" -> -1, "B" -> 1, "C" -> 1|>, 
"abc" -> <|"A" -> 1, "B" -> 1, "C" -> 1|>|>

Which can be transformed into a Dataset as :

ds = Dataset@dat

I would like to perform multiplications of combinaisons of several columns. The columns which must be multiplied are given by index :

header = Flatten@DeleteDuplicates@Keys@Values@dat;
index = Select[Subsets[header], Length@# >= 2 &];
(*index = {{"A", "B"}, {"A", "C"}, {"B", "C"}, {"A", "B", "C"}} <- these columns must be multiplied together*)

I have found on this post a way to achieve that for column A and B (index[[1]]) :

i = 1;
ds[All, Append[#, StringJoin@index[[i]] -> Times @@ {#A, #B}] &]

Now I'd like to apply this on each element of index. I've unsuccessfully tried

ds[All, Append[#,StringJoin@index[[i]] -> Times @@ Map[Slot, index[[i]]]] &]

with the hope that I can then iterate over index...

Jocelyn Minini
  • 612
  • 3
  • 8

2 Answers2

4

This seems to work well for me:

ds[All, 
   Append[#, 
     Map[
       cols |-> StringJoin[cols] -> Times @@ Through[Map[Lookup, cols][#]], 
       index]] &]

UPDATE: Incorporating @kglr suggestion, the resulting code is:

ds[All,
   Append[#, 
     Map[
       cols |-> StringJoin[cols] -> Times @@ Lookup[cols][#], 
       index]] &]
Gustavo Delfino
  • 8,348
  • 1
  • 28
  • 58
  • 4
    (+1) For a slightly simpler version you can replace Times @@ Through[Map[Lookup, cols][#]] with Times @@ Lookup[cols][#] – kglr Jan 10 '24 at 11:28
2

You can also do:

addColumns[indices_] := <|#, indices /. c : {Except[_List] ..} :> 
   Rule[StringJoin @ c, Times @@ KeyTake[#, c]]|> &

ds[All, addColumns[index]]

enter image description here

kglr
  • 394,356
  • 18
  • 477
  • 896