0
$\begingroup$

Missing values are a pain mathematically and computationally in general not just in WL, but I think this problem is more related to Dataset handling of warnings:

Select Works w/ a warning on Association lists::

{<|"a" -> "hey"|>, <| "a" -> Missing[]|>} // 
 Select[StringMatchQ[#a, "hey"] &] 
StringMatchQ::strse: "String or list of strings expected at position 1 in \!\(StringMatchQ[Missing[], \"hey\"]\). "
{<|"a" -> "hey"|>}

Fails as a Query:

Dataset[{<|"a" -> "hey"|>, <| "a" -> Missing[]|>} ] [
 Select[StringMatchQ[#a, "hey"] &]]

Missing["Failed"]

The Dataset docs only mentions Missing 4x and not in this context. Is there a workaround that lets it ignore such warnings?

$\endgroup$
  • $\begingroup$ One workaround for above is pre-replace missing values by empty string or similar, Query[All, {"a" -> Replace[Missing[] -> ""]}], violates the spirit of Missing $\endgroup$ – alancalvitti May 8 '15 at 18:39
  • $\begingroup$ Select[StringMatchQ[ToString[#a], "hey"] &]? $\endgroup$ – chuy May 8 '15 at 19:26
  • $\begingroup$ Why not just keep it Quiet. Dataset[{<|"a" -> "hey"|>, <|"a" -> Missing[]|>}][ Select[Function[Quiet[StringMatchQ[#a, "hey"]]]]] $\endgroup$ – Hans May 8 '15 at 19:39
  • $\begingroup$ As If[] anyone is listening: Dataset[{<|"a" -> "hey"|>, <|"a" -> Missing[]|>, <|"a" -> 23|>}][ Select[Function[If[Head[#a] == String , StringMatchQ[#a, "hey"]]]]] $\endgroup$ – Hans May 8 '15 at 20:13
5
$\begingroup$

In the example you give, your Query function asks if the value at element "a" is a string match for "hey". This generates the message because the value for a is not a string in the second row of your dataset.

For this particular case, one solution would be to require an exact match:

data = Dataset[{<|"a" -> "hey"|>, <|"a" -> Missing[]|>}];
Normal@data[Select[#a === "hey"&]]
{<|"a"->"hey"}|>

This works just fine in the example, but if you need to use an actual string match, e.g. of a string pattern, rather than a match using SameQ (===), I don't see a method that's particularly more elegant than changing your select function:

data[Select[StringQ[#a] && StringMatchQ[#a, "hey"] &]]

That said, as chuy noted in your question's comments, you can also force the #a to be a string:

data[Select[StringMatchQ[ToString[#a], "hey"] &]]

Or, as alancalvitti noted, you can pre-select the valid rows:

data[All, {"a" -> Replace[_Missing -> ""]}][Select[#a == "hey" &]]

Or, as Hans points out, you can use a Quiet[] form:

data[Select[Quiet[StringMatchQ[#a "hey"]] &]]

All of these produce correct results.

| improve this answer | |
$\endgroup$
  • $\begingroup$ This problem shows up generically w/ Missing, it's inconvenient to modify the logic just to handle those. $\endgroup$ – alancalvitti May 8 '15 at 22:41
  • $\begingroup$ In that case you might consider something like this: Block[{Missing}, Missing[___]:=""; data[Select[#a == "hey"&]]]; The block + Missing[___] := ""; will redefine all of the instances of Missing[...] (with any number of arguments) in your dataset while it evaluates it. Note that it will affect all missing entries, not just the ones you intend to be strings. $\endgroup$ – nben May 8 '15 at 22:48
  • $\begingroup$ Thanks butr even wrapping Block is a pain - the behavior should be specified globally. Also, ran into an edge case where data // Select[Quiet...] works but data[Select[Quiet...]]fails. $\endgroup$ – alancalvitti May 11 '15 at 18:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.