What I'm trying to do is to compare means after treatment p<0.05. First I saved p value through PROC SQL, then according to the p value to decide if needing to group the means or not. However, when p<.0001, the macro function %lsmeansOutput(P) always runs without LINES option as p>=0.05. When there is an exact p value<0.05, for example p=0.025, the macro function works correctly to show the mean grouping results.
Is there anyone can help me figure out the reason?
proc sql ; ** obtain p-value of trt;
select ProbF as intP into :intP
from Fixedp where Effect='Treatment';
run;
%macro lsmeansOutput (P);
%if &P<0.05 %then %do;
proc plm restore=&response.out;
ods exclude diffplot meanplot classlevels;
lsmeans treatment/lines;
run;
%end;
%else %do;
proc plm restore=&response.out;
ods exclude diffplot meanplot classlevels;
lsmeans treatment;
run;
%end;
%mend lsmeansOutput;
Thanks in advance!
Thanks for all your inputs, without your helps, I couldn't figure it out. Here it the code to solve my problem.
Using %lsmeansOutput(&P) instead of %lsmeansOutput(P) in when calling this macro function after format P to FORMAT 12.5.
proc sql ; ** obtain p-value of trt;
select ProbF format 12.5 as P into :P
from Fixedp where Effect='Treatment';
run;
%macro lsmeansOutput(P);
%if %sysevalf(&P<.05) %then %do;
proc plm restore=&response.out;
lsmeans treatment/lines adjust=Tukey;
run;
%put Yes branch;
%end;
%else %do;
proc plm restore=&response.out;
lsmeans treatment;
run;
%put No branch;
%end;
%mend lsmeansOutput;
%lsmeansOutput(&P);
When you extract the value from the db make sure to get the raw number not the formatted value. And when doing numerical comparisons with decimals wrap it in %SYSEVALF.
%if %sysevalf(&P<0.05) %then %do;
@RosieSAS wrote:
What I'm trying to do is to compare means after treatment p<0.05. First I saved p value through PROC SQL, then according to the p value to decide if needing to group the means or not. However, when p<.0001, the macro function %lsmeansOutput(P) always runs without LINES option as p>=0.05. When there is an exact p value<0.05, for example p=0.025, the macro function works correctly to show the mean grouping results.
Is there anyone can help me figure out the reason?
proc sql ; ** obtain p-value of trt; select ProbF as intP into :intP from Fixedp where Effect='Treatment'; run; %macro lsmeansOutput (P); %if &P<0.05 %then %do; proc plm restore=&response.out; ods exclude diffplot meanplot classlevels; lsmeans treatment/lines; run; %end; %else %do; proc plm restore=&response.out; ods exclude diffplot meanplot classlevels; lsmeans treatment; run; %end; %mend lsmeansOutput;
Thanks in advance!
When I call the Macro, I used % lsmeansOutput (intP), so that should not be a problem.
If you literally ran:
%macro lsmeansOutput (intP);
Then you started redefining the macro and SAS is going to take all input as part of the macro until you submit
%mend;
If instead you called the macro with intP as the input like this:
%lsmeansOutput (intP)
Then you are asking %sysevalf() to compare the letter i to the digit 0 and letter are always "larger" than digits.
Make sure to pass the VALUE of the macro variable in the macro call.
%lsmeansOutput(&intP)
Also make sure that your source variable ProbF is numeric an not character. If it is character and has a value like <0.001 then you are going to give %sysevalf() a very strange expression to evaluate.
You are not going to get the less than sign into the macro from a numeric variable with the code you showed. It does not matter what format is attached to the variable.
correction Actually it will put the formatted value, with leading spaces. Remove the format or use a different format. Use the TRIMMED keyword to avoid the leading spaces.
Anyway IF your macro variable has values that either start with < or 0 then you can just eliminate the first character and it should work.
884 %let x=<0.001 ; 885 %let y=0.10 ; 886 %let z=0.01 ; 887 %put &x -> %sysevalf(0.05>%substr(&x,2)); <0.001 -> 1 888 %put &y -> %sysevalf(0.05>%substr(&y,2)); 0.10 -> 0 889 %put &z -> %sysevalf(0.05>%substr(&z,2)); 0.01 -> 1
@RosieSAS wrote:
Thanks for your reply! No matter using &intP or intP, the results are the same here. ProbF is a numeric, the format is pvalue6.4.
First line in my response:
When you extract the value from the db make sure to get the raw number not the formatted value.
proc sql ; ** obtain p-value of trt;
select ProbF format=12.5 as intP into :intP
from Fixedp where Effect='Treatment';
run;
Thanks for all your replies!
When I specify the format of intP as format12.5 or format8.6 where intP<.0001, the print value is 0.00000. Then I tried the following code, and the result is 1. But I don't know why it still only ran the LSMEANS without LINES part. Below is the results from LOG window when using format8.6 in PROC SQL.
252 %put &intP is intP;
0.000000 is intP
253 %put %sysevalf(&intP<.05) is the logic;
1 is the logic
I tried @Tom 's method using %substr() without using FORMAT, and it works. The code is as following.
proc sql noprint; ** obtain p-value of trt;
select ProbF as intP into :intP
from Fixedp where Effect='Treatment';
run;
%macro lsmeansOutput(P);
%if %sysevalf(%substr(&intP,2)<.05) %then %do;
proc plm restore=&response.out;
ods exclude diffplot meanplot classlevels;
lsmeans treatment/lines adjust=Tukey;
run;
%end;
%else %do;
proc plm restore=&response.out;
ods exclude diffplot meanplot classlevels;
lsmeans treatment;
run;
%end;
%mend lsmeansOutput;
%lsmeansOutput(intP);
Thanks again for all the help! I got a lot.
I also tried the code below, the result in Log window is "xvalue is 0, intP value is <.0001". Any ideas?
%let x=%sysevalf(&intP<0.05); %put xvalue is &x, intP value is &intP;
Go back to where you create your INTp and fix it. You have created a character value that includes a < sign so the comparison fails.
If a variable has an assigned format, such as pvalue6.4 when you use the Proc sql select into the default format is applied. You need to make sure that the format used doesn't place any odd characters in the result.
data junk; probf = 0.00000567; format probf pvalue6.4; run; /* Wrong*/ proc sql ; ** obtain p-value of trt; select ProbF as intP into :intP from junk; quit; %put IntP is: &intp.; /* somewhat better*/ proc sql ; ** obtain p-value of trt; select ProbF format=8.6 as intP into :intP from junk; quit; %put IntP is: &intp.;
you get x=0 because the comparison is false.
You are evaluating %syevalf( <.0001<0.05 )
%let intp = <.0001; %let x=%sysevalf(&intP<0.05); %put xvalue is &x, intP value is &intP; %let nump = 0.0001; %let x=%sysevalf(&numP<0.05); %put xvalue is &x, NumP value is &numP;
Thanks for all the suggestions. I found an interesting problem that %sysevalf(&P<0.05 ) gave me different results for the same value of &P. The detail is, the P value is very small, after using format8.6 in proc sql, it shows 0.000000. When I ran %put alone, the result was 1.
However, when I ran the whole %lsmansOutput(P), the result was 0. Anyone knows the reason? Thanks!
395 %put Fail %sysevalf(&P<0.05);
Fail 1
396 %macro lsmeansOutput(P);
397 %if %sysevalf(&P<0.05) %then %do;
398 proc plm restore=&response.out;
399 ods exclude diffplot meanplot classlevels;
400 lsmeans treatment/lines adjust=Tukey;
401 run;
402 %put Success %sysevalf(&P<0.05);
403 %end;
404 %else %do;
405 proc plm restore=&response.out;
406 ods exclude diffplot meanplot classlevels;
407 lsmeans treatment;
408 run;
409 %put Fail %sysevalf(&P<0.05);
410 %end;
411 %mend lsmeansOutput;
412
413 %lsmeansOutput(P);
NOTE: PROCEDURE PLM used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds
Fail 0
I also tried simplified code, the %put also gave different results. I guess when P value is very small, or like 0.000000, the %sysevalf automatically treats P as a character variable. Please verify, thanks!
478 %macro lsmeansOutput(P);
479 %if %sysevalf(&P <.05) %then %do;
480 %put p=&P;
481 %end;
482 %else %do;
483 %put met else condition=&P;
484 %end;
485 %mend;
486 %lsmeansOutput(P);
met else condition=P
487 %put p=&P;
p=0.000000
You use the literal string P instead of the macro variable reference &P when calling the macro.
With the macro reference, the code works:
%let p=0.00000000001;
%put Fail %sysevalf(&P<0.05);
%macro lsmeansOutput(P);
%if %sysevalf(&P<0.05) %then %do;
%put Yes branch;
%end;
%else %do;
%put No branch;
%end;
%mend lsmeansOutput;
%lsmeansOutput(&P);
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.