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.

Tags:

Associations