BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
RosieSAS
Obsidian | Level 7

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! 

1 ACCEPTED SOLUTION

Accepted Solutions
RosieSAS
Obsidian | Level 7

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);

 

View solution in original post

21 REPLIES 21
Reeza
Super User

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! 


 

RosieSAS
Obsidian | Level 7
Thanks for your reply! However, it doesn't work. It still only outputs the means.
Reeza
Super User
Well...what is P? Where is it created? You create a variable called IntP but I don't see a P. Is that a typo or oversight?
RosieSAS
Obsidian | Level 7

When I call the Macro, I used % lsmeansOutput (intP), so that should not be a problem.

Tom
Super User Tom
Super User

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.

RosieSAS
Obsidian | Level 7
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.
Tom
Super User Tom
Super User

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

 

Reeza
Super User

@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;
RosieSAS
Obsidian | Level 7

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.

 

 

 

Reeza
Super User
You do not need the SUBSTR(). The value may be 0.0000 and the only difference between the outputs is the lines/adjust option. If you're not sure if the %IF/%THEN statements are working, remove the code and add explicit %PUT statements to test your logic first.
RosieSAS
Obsidian | Level 7

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;

 

ballardw
Super User

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;

 

RosieSAS
Obsidian | Level 7

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

 

Kurt_Bremser
Super User

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: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 21 replies
  • 2358 views
  • 10 likes
  • 5 in conversation