How can I get Merge to indicate missing values?
The most straightforward way to do this is to use KeyUnion
, which along with KeyIntersection
, allows for useful customization of what Merge
should do with missing keys. Its default behavior is pretty much exactly what you were asking for:
Merge[KeyUnion[{<|"a" -> 1, "b" -> 2|>, <|"a" -> 2, "c" -> 3|>}],
Identity]
(* <|"a" -> {1, 2}, "b" -> {2, Missing["KeyAbsent", "b"]},
"c" -> {Missing["KeyAbsent", "c"], 3}|> *)
If you want just the bare symbol Missing
as a sentinel value (which I personally avoid, because MissingQ
doesn't work for that), you can use the optional second argument:
Merge[KeyUnion[{<|"a" -> 1, "b" -> 2|>, <|"a" -> 2, "c" -> 3|>},
Missing &],
Identity]
(* <|"a" -> {1, 2}, "b" -> {2, Missing}, "c" -> {Missing, 3}|> *)
EDIT: As Sjord Smith points out in a comment below, you can use Missing[]
(with empty brackets) as a minimal sentinel value and MissingQ
will still pick it up:
result = Merge[KeyUnion[{<|"a" -> 1, "b" -> 2|>, <|"a" -> 2, "c" -> 3|>},
Missing[] &],
Identity]
(* <|"a" -> {1, 2}, "b" -> {2, Missing[]}, "c" -> {Missing[], 3}|> *)
Select[result, FreeQ[_?MissingQ]]
(* <|"a" -> {1, 2}|> *)
I know this already has an answer, but I'd like to point out that there is a built-in function that already does this for merging associations with Identity
:
GeneralUtilities`AssociationTranspose[{<|"a" -> 1, "b" -> 2|>, <|"a" -> 2, "c" -> 3|>}]
<|"a" -> {1, 2}, "b" -> {2, Missing["KeyAbsent", "b"]}, "c" -> {Missing["KeyAbsent", "c"], 3}|>
If you want to apply a merging function other than Identity
, simply map it over the result. Moreover, AssociationTranspose
is significantly faster than Merge
for large datasets, so that's also useful to keep in mind.