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

Hello SAS Community:

I am trying to highlight (traffic light) a row in ODS PDF output using PROC REPORT if the value of one variable is less than the value of another variable. I want to display the value of the variable of interest and surpress the display of the comparision variable within the same row. All the variables are available in the input dataset but SAS is reporting the following

 

NOTE: Variable NYPT_cor_p is uninitialized.

NOTE: The above message was for the following BY group:

Claim Type=I

NOTE: Variable NYPT_cor_p is uninitialized.

NOTE: The above message was for the following BY group:

Claim Type=E

NOTE: Variable NYPT_cor_p is uninitialized.

NOTE: The above message was for the following BY group:

Claim Type=A

 

I can assure that NYPT_cor_p is populated with valid data similar to what is contained pn PT_cor_p. If anyone can reply with examples I can use I would appreciate it. Thanks.

 

ODS listing close;

options orientation=landscape;

ods pdf file="D:\Data\indicator.pdf" style=SASdocprinter notoc;

proc report data=paysrc.summary_pct nowindows headline headskip split='*' style(header)=[fontsize=1] style(report)=[bordercolor = black] style(report)=[fontsize=-1] ;

options number nonumber nodate center; LABEL claim_type='Claim Type';

BY DESCENDING claim_type ;

columns facility _FREQ_ PT_cor PT_cor_p PT_nc PT_nc_p NYPT_cor NYPT_cor_p NYPT_nc NYPT_nc_p;

define facility / display 'Facility' style(column)=[fontsize=1];

define _FREQ_ / display 'Discharges' format=comma8. style(column)=[fontsize=1];

define PT_cor / display 'Payment Topology*Correctly*Mapped' format=comma8. style(column)=[fontsize=1];

define PT_cor_p / display '% Payment Topology*Correctly*Mapped' format=5.2 style(column)=[fontsize=1];

define PT_nc / display 'Payment Topology*Incorrectly*Mapped' format=comma8. style(column)=[fontsize=1];

define PT_nc_p / display '% Payment Topology*Incorrectly*Mapped' format=5.2 style(column)=[fontsize=1];

define NYPT_cor / noprint;

define NYPT_cor_p / noprint;

define NYPT_nc / noprint;

define NYPT_nc_p / noprint;

 

compute PT_cor_p;

if (PT_cor_p < NYPT_cor_p)

then do;

call define (_row_,'style','style={background=LIGR}');

end;

endcomp;

 

run;

ods pdf close;

ODS listing;

 

1 ACCEPTED SOLUTION

Accepted Solutions
Cynthia_sas
SAS Super FREQ

HI:

  As explained, you have several issues. PROC REPORT writes one report row at a time, working from left to right, "plopping" one report item at a time onto the report row. So, as an example, here is some pseudo-code that mimics your program:

 

proc report ... ;
column catvar var1 var2 var3 var4 var5;

define catvar / display;
define var1 /display;
define var2 / display;
define var3 / noprint sum;
define var4 /noprint sum;
define var5 / noprint sum;
compute var2;
  if var2 < var4 then do;
     call define(_row_, ... );
  end;
endcomp;
run;

  At the point in time when PROC REPORT is writing VAR2 on the report and is executing the COMPUTE block for VAR2, it has not yet written VAR4 on the report row, so there is no visibility of VAR4 for the IF test. In addition, any numeric variable without a usage of ORDER, GROUP or DISPLAY has a default usage of SUM...and that means that the correct reference for VAR4 (and for your NOPRINT items) is variable_name.SUM in the COMPUTE block.

 
So, my pseudo code above and your code will NOT work for 2 reasons:
1) var4 occurs in the column statement AFTER var2
2) you must refer to var4 by the compound name var4.sum (but even if you had var4.sum), it would NOT work in this instance. In my example, since VAR2 is a DISPLAY usage, it does not need to use a compound name for the IF statement.

Instead, you would need to do this...keep everything else the same and change the COMPUTE block for var4 instead of var2:
proc report ... ;
column catvar var1 var2 var3 var4 var5;

define catvar / display;
define var1 /display;
define var2 / display;
define var3 / noprint sum;
define var4 /noprint sum;
define var5 / noprint sum;
compute var4;
  if var2 < var4.sum then do;
     call define(_row_, ... );
  end;
endcomp;

OR, as suggested in an earlier post, you need to readjust the variables in your COLUMN statement so that VAR4 is to the left of VAR2 for the comparison:
proc report ... ;
column catvar var1 var4 var2 var3 var5;

define catvar / display;
define var1 /display;
define var2 / display;
define var3 / noprint sum;
define var4 /noprint sum;
define var5 / noprint sum;
compute var2;
  if var2 < var4.sum then do;
     call define(_row_, ... );
  end;
endcomp;
run;

 

  The bottom line is that PROC REPORT is not like a DATA step. There is no PDV (program data vector). PROC REPORT executes the COMPUTE block for a variable as soon as it is placing that variable on the report row. So if you have any kind of conditional processing in COMPUTE blocks, you need to make sure that all the variables you are testing have already been placed on the report row before your COMPUTE block executes.

 

  This is the reason that some people always put a "dummy" or "fake" variable at the end of their report row, because at the end of a row, all the variables and computed items have been written to the report row, so the COMPUTE block has visibility of all the items on the report row.

 

  Hope this helps,

cynthia

View solution in original post

7 REPLIES 7
ballardw
Super User

That message means that there are no non-missig values for the variable within the levels specified for the BY variable.

 

Proc freq data=paysrc.summary_pct ;

   tables NYPT_cor_p * claim_type;

run;

 

and you'll like see some cells with 0 counts. 

data_null__
Jade | Level 19

You need to move the variable referenced in the compute block to the left of the compute variable in the column statement.

Cynthia_sas
SAS Super FREQ

HI:

  As explained, you have several issues. PROC REPORT writes one report row at a time, working from left to right, "plopping" one report item at a time onto the report row. So, as an example, here is some pseudo-code that mimics your program:

 

proc report ... ;
column catvar var1 var2 var3 var4 var5;

define catvar / display;
define var1 /display;
define var2 / display;
define var3 / noprint sum;
define var4 /noprint sum;
define var5 / noprint sum;
compute var2;
  if var2 < var4 then do;
     call define(_row_, ... );
  end;
endcomp;
run;

  At the point in time when PROC REPORT is writing VAR2 on the report and is executing the COMPUTE block for VAR2, it has not yet written VAR4 on the report row, so there is no visibility of VAR4 for the IF test. In addition, any numeric variable without a usage of ORDER, GROUP or DISPLAY has a default usage of SUM...and that means that the correct reference for VAR4 (and for your NOPRINT items) is variable_name.SUM in the COMPUTE block.

 
So, my pseudo code above and your code will NOT work for 2 reasons:
1) var4 occurs in the column statement AFTER var2
2) you must refer to var4 by the compound name var4.sum (but even if you had var4.sum), it would NOT work in this instance. In my example, since VAR2 is a DISPLAY usage, it does not need to use a compound name for the IF statement.

Instead, you would need to do this...keep everything else the same and change the COMPUTE block for var4 instead of var2:
proc report ... ;
column catvar var1 var2 var3 var4 var5;

define catvar / display;
define var1 /display;
define var2 / display;
define var3 / noprint sum;
define var4 /noprint sum;
define var5 / noprint sum;
compute var4;
  if var2 < var4.sum then do;
     call define(_row_, ... );
  end;
endcomp;

OR, as suggested in an earlier post, you need to readjust the variables in your COLUMN statement so that VAR4 is to the left of VAR2 for the comparison:
proc report ... ;
column catvar var1 var4 var2 var3 var5;

define catvar / display;
define var1 /display;
define var2 / display;
define var3 / noprint sum;
define var4 /noprint sum;
define var5 / noprint sum;
compute var2;
  if var2 < var4.sum then do;
     call define(_row_, ... );
  end;
endcomp;
run;

 

  The bottom line is that PROC REPORT is not like a DATA step. There is no PDV (program data vector). PROC REPORT executes the COMPUTE block for a variable as soon as it is placing that variable on the report row. So if you have any kind of conditional processing in COMPUTE blocks, you need to make sure that all the variables you are testing have already been placed on the report row before your COMPUTE block executes.

 

  This is the reason that some people always put a "dummy" or "fake" variable at the end of their report row, because at the end of a row, all the variables and computed items have been written to the report row, so the COMPUTE block has visibility of all the items on the report row.

 

  Hope this helps,

cynthia

data_null__
Jade | Level 19

@Cynthia_sas wrote:

 

  This is the reason that some people always put a "dummy" or "fake" variable at the end of their report row, because at the end of a row, all the variables and computed items have been written to the report row, so the COMPUTE block has visibility of all the items on the report row.

 

  Hope this helps,

cynthia


 

@Cynthia_sas can you explain this use of dummy variable in more detail.  Are you saying you add a DUMMY as the rightmost column and COMPUTE DUMMY?

 

I've used DUMMY but for a different reason.  I can't remember and I can't produce an example of what I thought I use(d) it for.

 

Guess I'm the DUMMY.

Cynthia_sas
SAS Super FREQ

Hi:

  There's one example of using "DUMMYVAR" on pages 5-6 of this paper: http://support.sas.com/resources/papers/proceedings14/SAS388-2014.pdf with ACROSS usage.

 

  But, here's another example:

ods html file='c:\temp\fakevar.html';
  
proc report data=sashelp.class;
  title '1) need 2 COMPUTE blocks';
  column name age height weight;
  compute height;
    if height.sum gt 65 then do;
	   call define(_col_,'style','style={background=lightgreen}');
	end;
  endcomp;
  compute weight;
     if weight.sum gt 125 then do;
	   call define(_col_,'style','style={background=lightred}');
	 end;
  endcomp;
run;
    
proc report data=sashelp.class;
  title '2) One COMPUTE block under "FAKEVAR" -- my dummy variable';
  column name age height weight fakevar;
  define fakevar / computed ;
  compute fakevar;
    fakevar=0;
    if height.sum gt 65 then do;
	   call define('height.sum','style','style={background=lightgreen}');
	 end;
     if weight.sum gt 125 then do;
	   call define('weight.sum','style','style={background=lightred}');
	 end;
     if substr(name,1,1) = 'J' then do;
	   call define('name','style','style={background=lightblue}');
	 end;
     if age.sum = 13 then do;
	   call define('age.sum','style','style={background=lightyellow}');
	 end;
  endcomp;
run;
ods html close;

(I added some extra changes to the #2 code, just to illustrate that the last column can "touch" any previous column).

 

Hope this explains what I meant.

 

cynthia

nohassles
Obsidian | Level 7
Cynthia,

Thank you for your responses. My report looks great now after using your solution from a previous post. I definitely need to learn more of the inner workings of PROC REPORT.
nohassles
Obsidian | Level 7
Cynthia_sas, Thanks for your detailed solution. So much to learn, so little time. Kudos also to data_null__. nohassles

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

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
  • 7 replies
  • 14580 views
  • 5 likes
  • 4 in conversation