0
$\begingroup$

Some example data:

dt = <|"joe" -> <|"C1" -> 103, "C2" -> 104, "C3" -> 105, "C4" -> 107, "C5" -> 114|>,
  "tim" -> <|"C1" -> 101, "C2" -> 102, "C3" -> Missing[_], "C4" -> 101, "C5" -> 111|>,
  "ann" -> <|"C1" -> 102, "C2" -> 103, "C3" -> 103, "C4" -> 105, "C5" -> 114|>,
  "bob" -> <|"C1" -> 103, "C2" -> 103, "C3" -> 103, "C4" -> 104, "C5" -> 113|>|>

I want to apply a function to a rectangular subset of a matrix (given as an Association of Associations) by specifying the Keys. Since I couldn't find a suitable inbuilt function I wrote:

MapAtKeys[dt_, fn_, {row_, col_}] :=
 Module[{pos, rp, cp},
  pos[d_, p_] := 
   Span @@ MinMax @ Flatten @ Values @ PositionIndex[Keys @ d][[p]];
  rp = pos[dt, row];
  cp = pos[dt[[1]], col];
  MapAt[fn, dt /. Missing[_] :> mis, {rp, cp}] /. mis :> Missing[_]
  ]

To skip missing values:

Plus[___, mis, ___] ^= mis;
Times[___, mis, ___] ^= mis;
Style[___, mis, ___] ^= mis;

MapAtKeys[dt, # - 100 &, {{"joe", "ann"}, {"C3", "C4"}}] // Dataset

enter image description here

MapAtKeys[dt, Style[#, Red] &, {All, {"C3", "C4"}}] // Dataset

enter image description here

The weakest point of this solution is the handling of missing values, because I have to add function after function to the UpSet - definitions of mis. Also, the detour of converting the Keys to Position - indices is far from perfect.

How would a better solution look like?

$\endgroup$
2
  • $\begingroup$ Would the MapAtKey resource function help you out here? $\endgroup$
    – MarcoB
    Aug 12, 2023 at 14:00
  • $\begingroup$ No, MapAtKey doesn't work with matrices. Thanks anyway :) $\endgroup$
    – eldo
    Aug 12, 2023 at 14:36

1 Answer 1

2
$\begingroup$
mF[f_, rows_, columns_] := MapAt[
  ReplaceAll[{m_Missing :> m, x_ :> f[x]}], 
  Tuples[{rows, columns}]]

Examples:

mF[# - 100 &, {"joe", "ann"}, {"C3", "C4"}]@dt // Dataset

enter image description here

mF2[Style[#, Red] &, {"joe", "ann"}, {"C3", "C4"}]@dt // Dataset

enter image description here

mF[Style[#, Red] &, {All}, {"C3", "C4"}]@dt // Dataset

enter image description here

$\endgroup$
1
  • 1
    $\begingroup$ Perfect solution. Nice how you skip the missing values using ReplaceAll - Thank you $\endgroup$
    – eldo
    Aug 13, 2023 at 5:14

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.