Recently, I needed to detect whether a matrix consists entirely of missing values. I wrote the following module:
proc iml; /** Module to detect whether all elements of a matrix are missing values. Works for both numeric and character matrices. Version 1 (not optimal) **/ start isMissing(x); if type(x)='C' then missVal = " "; /** character missing **/ else missVal = .; /** numeric missing **/ return (all(x=missVal)); finish; /** test the module on some matrices **/ x = {. . ., . . .}; y = {" ", " ", " "}; xIsMissing = isMissing(x); yIsMissing = isMissing(y); print xIsMissing yIsMissing; |
I was quite proud of myself because I had written a single function module that handles both numeric and character matrices. The beauty of the module, I thought, was that it branches on the type of the argument (character or numeric) and always compares the argument with the corresponding SAS missing value. Brilliant!
Well, maybe not so brilliant. As they say, pride comes before the fall. Within minutes, I had thought of a better way to write the function:
/** Version 2 (better) **/ start isMissing(x); return (all(cmiss(x))); finish; |
Why is this module better? It calls the CMISS function in Base SAS software. The CMISS function handles both character and numeric missing values. In a SAS/IML program, it returns a matrix that has the same dimensions as its argument. If x consists entirely of missing values, then cmiss(x) consists entirely of ones.
I had reduced the module to a single line, so I was feeling good about that. But then I realized I don't even need the module at all. I can just write:
xIsMissing = all(cmiss(x)); /** no module at all (best) **/ |
The irony of this story is that I had failed to heed the advice that I often give to others: "Remember that you can call functions in Base SAS software from SAS/IML programs."
I guess that advice is similar to Obi-Wan Kenobi saying, "Use the Force, Luke!" It is helpful advice, but only if the listener is trained in the ways of the Force (or, in this case, the DATA step). While writing the module, I was fortunate to hear a voice whispering in my head: "Use the CMISS function, Rick."
1 Comment
This is hilarious. I like how your blog is entertaining, and yet I always learn something too. Keep up the good work.