I'm not an expertise on generating report. So I'm hoping someone could help me revise the program below so it could look more close to the expected table shell. The program works well but I was asked to have variable name (vardesc in my program) and related categories (var_val in my program) in the same column. Below is the desirable table shell (shown as first picture). Next to it is what I generated from my program.
Another issue is that the program was excuted under SAS Studio enviroment. For some reason, table result from mean (SD) is not exactly what I expected (e.g. 2.777, 0.966). Is there any quick solution to keep one decimal here? Thanks for your help!
proc report data=outputw style(report)={just=left} colwidth=6
style(header)={just=center protectspecialchars=off font_weight=BOLD background=white}
headline headskip split="/" missing;
column group ('Characteristics' vardesc var_val)
("Overall"
("N" col1_cohort1) ("%" col2_cohort1) )
("Moderate to Severe"
("N" col1_cohort2) ("%" col2_cohort2) )
("Trial Similar"
("N" col1_cohort3) ("%" col2_cohort3) )
("General Population"
("N" col1_cohort4) ("%" col2_cohort4) )
;
define group /group noprint order=data;
define vardesc /group ' ' order=data style=[just=l];
define var_val / display ' ' order=data style(column)={width=1 in just=l};
define col1_cohort1 /display ' ' format=comma8. style(column)={cellwidth=0.5in just=c };
define col2_cohort1 /display ' ' format=comma5.1 style(column)={cellwidth=0.5in just=c };
define col1_cohort2 /display ' ' format=comma10. style(column)={cellwidth=0.5in just=c };
define col2_cohort2 /display ' ' format=comma5.1 style(column)={cellwidth=0.5in just=c};
define col1_cohort3 /display ' ' format=comma8. style(column)={cellwidth=0.5in just=c };
define col2_cohort3 /display ' ' format=comma5.1 style(column)={cellwidth=0.5in just=c };
define col1_cohort4 /display ' ' format=comma10. style(column)={cellwidth=0.5in just=c };
define col2_cohort4 /display ' ' format=comma5.1 style(column)={cellwidth=0.5in just=c};
compute before group/ style=[just=l font_weight=bold];
line @1 group group.;
endcomp;
compute var_val;
call define(_col_,"style","style={leftmargin=.15in font_weight=medium}");
endcomp;
compute col1_cohort1;
if var_val in ('Mean (SD)') then call define(_col_,"format","format=comma5.1");
endcomp;
compute col1_cohort2;
if var_val in ('Mean (SD)') then call define(_col_,"format","format=comma5.1");
endcomp;
compute col1_cohort3;
if var_val in ('Mean (SD)') then call define(_col_,"format","format=comma5.1");
endcomp;
compute col1_cohort4;
if var_val in ('Mean (SD)') then call define(_col_,"format","format=comma5.1");
endcomp;
run;quit;
title;
ods excel close
Some of what you are asking is pretty easy for Proc Tabulate. See the following example with a training data set you should have in your SAS install.
proc tabulate data=sashelp.cars; where make in ('Audi' 'Chevrolet' 'Dodge' 'Ford' 'Hyundai' 'Toyota' 'Volvo'); class origin make type drivetrain cylinders ; table origin make type, (All='All Cars' Drivetrain cylinders)*(n pctn='%') /misstext=' ' nocellmerge ; run;
The NOCELLMERGE is what provides the row of empty cells along the variable on the left margin.
If the variable has a Label assigned that will appear instead of the variable name by default.
In proc tabulate you have several "dimensions" that are separated by a comma(s) in the Table statement. With one comma as shown the first bit before the comma is the row header values, then the columns. If you have 2 commas, the first bit becomes a "page" or separate table.
If you use an * between items then they nest. So the above was asking for N and Pctn for the three Class variables.
You can nest class variables as well: Table Origin * Make <other stuff> would have a left column with values of origin and the makes in that origin following
Variables that are to be used as categories go on a CLASS statement. If you are going to calculate means, sums or other statistics except N and percentages the variables must go a VAR statement. Caution: Be default Proc Tabulate will exclude any observations that have missing values for one or more of the Class variables. This behavior can be overridden using the option /missing; on a class statement, which makes missing a valid category for the report.
Proc tabulate will also allow multiple Table statements . Such as
proc tabulate data=sashelp.cars; where make in ('Audi' 'Chevrolet' 'Dodge' 'Ford' 'Hyundai' 'Toyota' 'Volvo'); class origin make type drivetrain cylinders ; table origin make type, (All='All Cars' Drivetrain cylinders)*(n pctn='%') /misstext=' ' nocellmerge ; table origin*make , (All='All Cars' Drivetrain cylinders)*(n pctn='%') /misstext=' ' nocellmerge ; table make*type, (All='All Cars' Drivetrain cylinders)*(n pctn='%') /misstext=' ' nocellmerge ; run;
So sometimes it is easier / nicer appearance to have part in a separate table (page length as a limit when printing for example).
Tabulate will let you nest items in rows and columns as well which isn't really a Proc Report strong point. Example:
proc tabulate data=sashelp.cars; where make in ('Audi' 'Chevrolet' 'Dodge' 'Ford' 'Hyundai' 'Toyota' 'Volvo'); class origin make type drivetrain cylinders ; table origin*( make All='All makes'), type*(drivetrain All='All drivetrains')*(cylinders All='All cylinders')*(n pctn) /misstext=' ' nocellmerge ; run;
Note the keyword ALL is used a bit like the Proc Report Break to create summaries of groups.
Caution: If start using VAR variables and statistics you can't cross them with most other statistics
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
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.