Hi all,
Why I run the data B, the log report " Missing values were generated as a result of performing an operation on missing value"
But the log of data C is clean.
I want to use the data B with the clean log. Thanks.
data a; a="20DEC2019:00:00:00.000"dt;output; a=.;output; format a DATETIME22.3; run; data b; set a; c=ifc(a ne .,put(datepart(a),date9.),''); run; data c; set a ; if a ne . then c=put(datepart(a),date9.); else c=''; run;
Sadly, SAS made the decision that the ifx() functions were executed by the compiler like every other function.
This means that all the function parameters are processed all the time.
The consequences of this decision are:
1. Your B code generates a message, as you have observed. There is no doubt that this undermines the usefulness of the function.
2. There is a performance cost as both the true and false parameters are executed, when only one of them is ever needed.
I can't think of a good reason for this decision.
Sadly, SAS made the decision that the ifx() functions were executed by the compiler like every other function.
This means that all the function parameters are processed all the time.
The consequences of this decision are:
1. Your B code generates a message, as you have observed. There is no doubt that this undermines the usefulness of the function.
2. There is a performance cost as both the true and false parameters are executed, when only one of them is ever needed.
I can't think of a good reason for this decision.
I see one advantage: you can use lag() "conditionally".
@Kurt_Bremser You found the silver lining! 🙂
I even think that this behavior is the explicit purpose of the ifc and ifn functions. Otherwise a simple if-then-else is all that's needed, and we've been coding that since the beginning of non-assembler programming languages.
When a function is called, the argument values need to be pushed onto the stack, and the function retrieves them from there. If you do not want this to happen, the data step compiler would need extra coding to recognize the ifc/ifn function and then translate the whole call into a normal if-then-else statement; something that the programmer can easily do on their own, if non-execution of a branch is wanted.
@Kurt_Bremser Your explanation makes sense.
I find a code such as
VAR = ifn(&test1, 1 , ifn(&test2, 2 , ifn(&test3, 3, 4 )));
much more legible than
if &test1 then VAR= 1; else if &test2 then VAR= 2; else if &test3 then VAR= 3; else VAR= 4;
and I often use if() just for this reason. The example given (dealing with missing values) is also a hindrance.
So I wish the compiler behaved as if it found a if then test; I don't think the extra compiler logic to identify this would be of any consequence.
That's just me though. I understand your reasons and they are valid too.
Not sure I see how that is better pattern. Turning logic into function calls might make sense in something like Excel spreadsheet where everything has to be a function. If it is just the symmetry you like then use a SELECT statement instead of nested if/then/else.
@ChrisNZ wrote:
@Kurt_Bremser Your explanation makes sense.
I find a code such as
VAR = ifn(&test1, 1 , ifn(&test2, 2 , ifn(&test3, 3, 4 )));much more legible than
if &test1 then VAR= 1; else if &test2 then VAR= 2; else if &test3 then VAR= 3; else VAR= 4;and I often use if() just for this reason. The example given (dealing with missing values) is also a hindrance.
So I wish the compiler behaved as if it found a if then test; I don't think the extra compiler logic to identify this would be of any consequence.
That's just me though. I understand your reasons and they are valid too.
I agree that a function is not best suited for this kind of test.
But it is much more legible in this case, imho.
Hence my preference. I put legibility first here.
@ChrisNZ described the root cause. For your specific sample code using format dtdate. would allow you to not use function datepart() which throws the note. Using format dtdate. even removes the need for conditional logic.
data a;
a="20DEC2019:00:00:00.000"dt;output;
a=.;output;
format a DATETIME22.3;
run;
data b;
set a;
c=put(a, dtdate9.);
/* c=ifc(a ne .,put(a,dtdate9.),'');*/
run;
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.