# Apply a function to a rectangular subgrid with missing values

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


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


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?

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

## 1 Answer

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


Examples:

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


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


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


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